C + PicoSAT , 2345 995 952 byte
#include<picosat.h>
#define f(i,a)for(i=a;i;i--)
#define g(a)picosat_add(E,a)
#define b calloc(z+1,sizeof z)
#define e(a,q)if(a)A[q]^A[p]?l[q]++||(j[++k]=q):s[q]||(i[q]=p,u(q));
z,F,v,k,n,h,p,q,r,C,*x,*A,*i,*l,*s,*j,*m;u(p){s[m[++n]=p]=1;e(p%F-1,p-1)e(p%F,p+1)e(p>F,p-F)e(p<=F*v-F,p+F)}t(){f(q,k)l[j[q]]=0;f(q,n)s[m[q]]=0;k=n=0;i[p]=-1;u(p);}main(){void*E=picosat_init();if(scanf("%d,%d",&F,&v)-2)abort();z=F*v;for(x=b;scanf("%d,%d,%d",&r,&p,&q)==3;g(p),g(0))x[p=F-p+q*F]=r;f(p,F*v-F)if(p%F)g(p),g(p+1),g(p+F),g(p+F+1),g(0);for(A=b,i=b,l=b,s=b,j=b,m=b;!C;){picosat_sat(E,C=h=-1);f(p,F*v)A[p]=picosat_deref(E,p)>0,i[p]=0;f(p,F*v)if(x[p])if(i[q=p]){for(g(-q);i[q]+1;)q=i[q],g(-q);g(C=0);}else if(t(),r=n-x[p]){f(q,r<0?k:n)g(r<0?j[q]:-m[q]);g(C=0);}f(p,F*v)if(!i[p])if(t(),A[p]){g(-++z);f(q,k)g(j[q]);g(C=0);f(q,n)g(-m[q]),g(z),g(0);}else{C&=h++;f(q,k)g(-j[q]);g(++z);g(++z);g(0);f(q,F*v)g(s[q]-z),g(q),g(0);}}f(p,F*v)putchar(A[p]?35:46),p%F-1||puts("");}
Hãy thử trực tuyến!
(Cảnh báo: liên kết TIO này là URL 30 kilobyte có chứa bản sao được rút gọn của PicoSAT 965, do đó bạn có thể không tải được nó trong một số trình duyệt, nhưng nó tải ít nhất Firefox và Chrome.)
Làm thế nào nó hoạt động
Chúng tôi khởi tạo bộ giải SAT với một biến cho mỗi ô (đất hoặc nước) và chỉ các ràng buộc sau:
- Mỗi ô được đánh số là đất.
- Mỗi hình chữ nhật 2 × 2 có ít nhất một vùng đất.
Phần còn lại của các ràng buộc khó mã hóa trực tiếp vào SAT, vì vậy thay vào đó chúng tôi chạy bộ giải để lấy mô hình, chạy một chuỗi các tìm kiếm theo chiều sâu để tìm các vùng được kết nối của mô hình này và thêm các ràng buộc bổ sung như sau:
- Đối với mỗi ô được đánh số trong một vùng đất quá lớn, hãy thêm một ràng buộc rằng phải có ít nhất một ô nước trong số các ô đất hiện tại trong vùng đó.
- Đối với mỗi ô được đánh số trong một vùng đất quá nhỏ, hãy thêm một ràng buộc rằng phải có ít nhất một ô đất trong số các ô nước hiện tại giáp với vùng đó.
- Đối với mỗi ô được đánh số trong cùng một vùng đất với một ô được đánh số khác, hãy thêm một ràng buộc rằng phải có ít nhất một ô nước dọc theo đường đi của các ô đất hiện tại giữa chúng (được tìm thấy bằng cách đi bộ con trỏ cha mẹ còn sót lại từ tìm kiếm đầu tiên ).
- Đối với mọi vùng đất bao gồm không có ô được đánh số, hãy thêm các ràng buộc
- Tất cả các tế bào đất hiện tại phải là nước, hoặc
- ít nhất một trong những tế bào nước hiện tại giáp với khu vực đó phải là đất liền.
- Đối với mọi vùng nước, hãy thêm các ràng buộc
- tất cả các tế bào nước hiện tại phải là đất, hoặc
- mọi tế bào không phải là những tế bào nước hiện tại phải là đất, hoặc
- ít nhất một trong những tế bào đất hiện tại giáp với khu vực đó phải là nước.
Tận dụng giao diện gia tăng cho thư viện PicoSAT, chúng ta có thể ngay lập tức chạy lại bộ giải bao gồm các ràng buộc được thêm vào, bảo toàn tất cả các suy luận trước đó của bộ giải. PicoSAT cung cấp cho chúng tôi một mô hình mới và chúng tôi tiếp tục lặp lại các bước trên cho đến khi giải pháp hợp lệ.
Điều này là hiệu quả rõ rệt; nó giải quyết các trường hợp 15 × 15 và 20 × 20 trong một phần rất nhỏ của một giây.
(Cảm ơn Lopsy đã gợi ý ý tưởng này về việc hạn chế tương tác các vùng được kết nối trong một bộ giải SAT gia tăng, một thời gian trước.)
Một số trường hợp thử nghiệm lớn hơn từ puzzle-nurikabe.com
Một trang ngẫu nhiên gồm các câu đố khó 15 × 15 ( 5057541 , 5122197 , 5383030 , 6275294 , 6646970 , 6944232 ):
15,15 1,5,1 3,9,1 5,4,2 1,6,2 2,11,2 2,2,3 3,9,3 2,4,4 1,10,4 5,12,4 3,1,5 1,3,5 3,8,5 1,13,5 5,5,6 1,12,6 1,2,8 2,9,8 1,1,9 2,6,9 6,11,9 3,13,9 5,2,10 2,4,10 4,10,10 1,5,11 2,12,11 2,3,12 2,8,12 5,10,12 1,5,13 1,9,13 1,6,14 1,8,14
15,15 4,2,0 2,5,0 1,3,1 2,14,2 1,3,3 2,11,3 1,13,3 1,5,4 11,7,4 1,9,4 1,4,5 1,8,5 2,10,5 12,14,5 3,5,6 1,4,7 2,10,7 3,9,8 4,0,9 1,4,9 1,6,9 3,10,9 1,5,10 1,7,10 8,9,10 1,1,11 10,3,11 2,11,11 6,0,12 1,11,13 2,9,14 1,12,14
15,15 2,2,0 8,10,0 2,3,1 2,14,2 2,3,3 3,5,3 3,9,3 2,11,3 5,13,3 6,0,4 3,7,4 3,3,5 2,11,5 2,6,6 1,8,6 1,4,7 2,10,7 1,6,8 2,8,8 5,3,9 2,11,9 2,7,10 7,14,10 2,1,11 4,3,11 2,5,11 1,9,11 2,11,11 2,0,12 4,6,13 1,11,13 3,4,14 1,12,14
15,15 2,0,0 2,4,0 3,6,1 2,10,1 1,13,1 2,5,2 2,12,2 3,0,3 2,2,3 4,7,3 2,9,3 1,14,3 1,4,4 1,8,4 2,12,5 4,2,6 3,4,6 1,14,6 7,7,7 1,10,8 2,12,8 3,2,9 2,14,9 2,0,10 2,6,10 1,10,10 2,5,11 4,7,11 2,12,11 1,14,11 3,2,12 3,9,12 1,1,13 2,4,13 3,8,13 2,10,14 5,14,14
15,15 1,3,0 1,14,0 3,7,1 3,10,1 2,13,1 3,1,2 4,5,2 2,12,3 3,3,4 1,8,4 1,1,5 3,5,5 1,9,5 5,13,5 3,3,6 1,8,6 2,2,7 2,12,7 1,6,8 1,8,8 2,11,8 2,1,9 4,5,9 2,9,9 2,13,9 2,6,10 4,11,10 1,2,11 3,9,12 2,13,12 3,1,13 2,4,13 3,7,13 1,0,14
15,15 2,8,0 2,4,1 2,7,1 1,10,1 6,4,3 1,1,4 12,5,4 3,11,4 5,13,4 3,10,5 3,0,6 1,6,6 2,8,6 4,13,7 2,3,8 1,6,8 3,8,8 2,14,8 2,4,9 5,1,10 4,3,10 1,9,10 6,13,10 3,8,11 1,10,11 3,4,13 2,7,13 3,10,13 1,6,14 1,14,14
Một trang ngẫu nhiên gồm 20 × 20 câu đố thông thường ( 536628 , 3757659 ):
20,20 1,0,0 3,2,0 2,6,0 1,13,0 3,9,1 3,15,1 2,7,2 3,13,2 3,0,3 2,3,3 3,18,3 3,5,4 2,9,4 2,11,4 2,16,4 1,0,5 2,7,5 1,10,5 1,19,5 3,2,6 1,11,6 2,17,6 2,0,7 3,4,7 5,6,7 2,9,7 4,13,7 3,15,7 1,3,8 1,10,8 1,14,9 2,18,9 3,1,10 2,4,10 1,8,10 1,10,10 3,12,10 3,16,10 1,9,11 1,17,11 2,19,11 2,0,12 2,2,12 1,4,12 4,6,12 2,13,12 2,15,12 1,14,13 2,17,13 1,3,14 2,5,14 4,7,14 2,15,14 3,0,15 1,2,15 2,13,15 3,18,15 3,7,16 7,10,16 1,17,16 2,0,17 2,3,17 2,5,17 3,11,17 3,15,17 1,0,19 1,2,19 1,4,19 2,6,19 5,8,19 1,11,19 1,13,19 3,15,19 2,18,19
20,20 1,0,0 1,4,0 5,8,0 1,17,0 1,19,0 2,17,2 3,6,3 2,10,3 2,12,3 4,14,3 6,0,4 3,4,4 4,7,4 1,11,4 1,18,4 1,6,5 3,12,5 4,15,5 4,4,6 2,16,6 2,19,6 6,0,7 3,10,7 2,12,8 2,17,8 3,3,9 2,5,9 4,8,9 2,10,9 3,0,10 1,2,10 5,14,10 2,16,10 2,19,10 7,7,11 3,12,12 2,17,12 2,2,13 4,4,13 3,6,13 4,14,13 3,0,14 1,3,14 1,5,14 3,16,14 1,2,15 1,9,15 2,11,15 5,13,15 3,19,15 1,4,16 3,6,16 1,3,17 1,12,17 1,14,17 1,16,17 6,0,19 2,2,19 3,5,19 2,7,19 5,9,19 1,11,19 2,13,19 1,15,19 4,17,19