【洛谷P1228】地毯填補問題【分治】【遞迴】【DFS】
阿新 • • 發佈:2018-12-10
題目大意:
題目連結:https://www.luogu.org/problemnew/show/P1228 用L型地毯鋪滿一個邊長為的正方形,要求有一個特殊點不能鋪且其他每個點都僅被一個地毯鋪到的方案。 L型地毯為以下幾種圖案:
思路:
首先考慮的情況。假設這個特殊點在,那麼很明顯正確的填法是這樣的: 那麼接下來就要擴大到了: 這時候,另外三個的未上色格子就沒有特殊點了,也就沒法像一開始的的格子做。那麼可不可以給每個的格子都增加一個特殊點呢? 答案很明顯是可以的。只要在四個的格子的正中間旁邊的3個白色格子都填上同一種顏色,然後再分別處理三個的格子就可以! 那麼再分別處理三個格子,得到 那麼同理,當我們擴充到的格子時候,也用同樣的方法,現將中間點旁邊的白點標記為特殊點。 然後同理。。。 那麼就可以推出大小的答案啦! 那麼,如果要我們求大小的答案,那麼就首先找到它的中點,判斷特殊點再那邊,然後就往那邊遞迴,就變成了,之後一直遞迴下去直到變成,然後就像上面說的一樣慢慢染色輸出啦!
程式碼:
#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;
}