1. 程式人生 > >【洛谷P1228】地毯填補問題【分治】【遞迴】【DFS】

【洛谷P1228】地毯填補問題【分治】【遞迴】【DFS】

題目大意:

題目連結:https://www.luogu.org/problemnew/show/P1228 用L型地毯鋪滿一個邊長為2k的正方形,要求有一個特殊點不能鋪且其他每個點都僅被一個地毯鋪到的方案。 L型地毯為以下幾種圖案: 這裡寫圖片描述

思路:

首先考慮2×2的情況。假設這個特殊點在(1,1),那麼很明顯正確的填法是這樣的: 這裡寫圖片描述 那麼接下來就要擴大到4×4了: 這裡寫圖片描述 這時候,另外三個2×2的未上色格子就沒有特殊點了,也就沒法像一開始的2×2的格子做。那麼可不可以給每個2×2的格子都增加一個特殊點呢? 答案很明顯是可以的。只要在四個

2×2的格子的正中間旁邊的3個白色格子都填上同一種顏色,然後再分別處理三個2×2的格子就可以這裡寫圖片描述 那麼再分別處理三個2×2格子,得到 這裡寫圖片描述 那麼同理,當我們擴充到8×8的格子時候,也用同樣的方法,現將中間點旁邊的白點標記為特殊點。 這裡寫圖片描述 然後同理。。。 這裡寫圖片描述 那麼就可以推出210大小的答案啦! 假裝有圖片.jpg 那麼,如果要我們求210大小的答案,那麼就首先找到它的中點,判斷特殊點再那邊,然後就往那邊遞迴,就變成29×29了,之後一直遞迴下去直到變成2\time2,然後就像上面說的一樣慢慢染色輸出啦!

程式碼:

#include <cstdio>
using namespace std; int n,k,a[1201][1201]; void dfs(int x1,int y1,int x2,int y2,int X,int Y) { if (x2-x1==1&&y2-y1==1) //變成了2*2 { if (X==x1&&Y==y1) printf("%d %d 1\n",x2,y2); if (X==x1&&Y==y2) printf("%d %d 2\n",x2,y1); if (X==x2&&Y==y1) printf
("%d %d 3\n",x1,y2); if (X==x2&&Y==y2) printf("%d %d 4\n",x1,y1); return; } int x=(x2-x1+1)/2+x1-1; int y=(y2-y1+1)/2+y1-1; //取出中點 //接下來就是分治特殊點的位置,往那個方向搜尋。 if (X<=x&&Y<=y) { dfs(x1,y1,x,y,X,Y); printf("%d %d 1\n",x+1,y+1); dfs(x+1,y1,x2,y,x+1,y); dfs(x+1,y+1,x2,y2,x+1,y+1); dfs(x1,y+1,x,y2,x,y+1); } if (X<=x&&Y>y) { dfs(x1,y+1,x,y2,X,Y); printf("%d %d 2\n",x+1,y); dfs(x1,y1,x,y,x,y); dfs(x+1,y1,x2,y,x+1,y); dfs(x+1,y+1,x2,y2,x+1,y+1); } if (X>x&&Y<=y) { dfs(x+1,y1,x2,y,X,Y); printf("%d %d 3\n",x,y+1); dfs(x+1,y+1,x2,y2,x+1,y+1); dfs(x1,y1,x,y,x,y); dfs(x1,y+1,x,y2,x,y+1); } if (X>x&&Y>y) { dfs(x+1,y+1,x2,y2,X,Y); printf("%d %d 4\n",x,y); dfs(x1,y1,x,y,x,y); dfs(x1,y+1,x,y2,x,y+1); dfs(x+1,y1,x2,y,x+1,y); } } int main() { int x,y; scanf("%d%d%d",&k,&x,&y); n=1; for (int i=1;i<=k;i++) n*=2; //我就不用(1<<n) dfs(1,1,n,n,x,y); return 0; }