AOJ 859 地毯填补问题 【分治】

来源:互联网 发布:网络变压器生产工艺 编辑:程序博客网 时间:2024/04/27 16:50

题面:

相传在一个古老的阿拉伯国家里,有一座宫殿。宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站立的地方外的所有地方盖上,美丽漂亮聪慧的公主就是他的人了。公主这一个方格不能用地毯盖住,毯子的形状有所规定,只能有四种选择(如图2):
这里写图片描述

并且每一方格只能用一层地毯,迷宫的大小为2的k次方见方的方形。当然,也不能让公主无限制的在那儿等,对吧?由于你使用的是计算机,所以实现时间为1秒。
Input
输入共2行。
第一行:k,即给定被填补迷宫的大小为2^k(0第二行:x y,即给出公主所在方格的坐标(x为行坐标,y为列坐标),x和y之间有一个空格隔开。
Output
将迷宫填补完整的方案:每一补(行)为 x y c (x,y为毯子拐角的行坐标和列坐标,c为使用毯子的形状,具体见上面的图1,毯子形状分别用1、2、3、4表示,x、y、c之间用一个空格隔开)。
Sample Input
3
3 3
Sample Output
5 5 1
2 2 4
1 1 4
1 4 3
4 1 2
4 4 1
2 7 3
1 5 4
1 8 3
3 6 3
4 8 1
7 2 2
5 1 4
6 3 2
8 1 2
8 4 1
7 7 1
6 6 1
5 8 3
8 5 2
8 8 1

大致思路:

首先根据题面中没有对于不可能铺满的情况输出“NO或者imposslble”可以猜想:一个大小为2^k次方的正方形,任意一个方格被涂黑后。用图二中的图形可以将其填满。
当k=1时,结论显然是成立的。当k=2时,可以在图中间放一个砖,使得分出的每1/4的图形都有一个被染色
这里写图片描述
浅灰色代表一开始随机被涂黑的地方,深灰色代表砖块。
所以当k更大时,都能按照图上的情况分成大小为2^(k-1)的正方形,并且每一个正方形都有一块被涂黑,无法覆盖。这样利用分治算法进行问题的缩小化。
确定这样的思路之后,可以发现样例输出的顺序刚好是这样分治铺地砖的顺序。每次首先向左上角进行分治,然后是右上角、左下角、右下角。刚好满足样例的输出。

最后是对于正方形的描述,可以利用左上角的坐标和右下角的坐标对正方形进行定位。

代码:

#include<iostream>#include<cstring>#include<cstdio>using namespace std;bool mp[1<<10][1<<10];int k;int check(int x1,int y1,int x2,int y2)//检查被涂黑的区域在所查方块的哪个区域{    int p=0;    for(int i=x1;i<=x2;++i)    for(int j=y1;j<=y2;++j){        if(mp[i][j]){            if(i<=(x1+x2)/2){                if(j<=(y1+y2)/2)                    p=1;                else                    p=2;            }else{                if(j<=(y1+y2)/2)                    p=3;                else                    p=4;            }            return p;        }    }}void print()//debug用{    for(int i=1;i<=1<<k;++i){        for(int j=1;j<=1<<k;++j)            cout<<mp[i][j]<<" ";        cout<<endl;    }}void dfs(int x1,int y1,int x2,int y2){    //cout<<"x1="<<x1<<" y1="<<y1<<" x2="<<x2<<" y2="<<y2<<endl;    int x=(x1+x2)/2+1;    int y=(y1+y2)/2+1;    int ans=check(x1,y1,x2,y2);    if(ans==1){        cout<<x<<" "<<y<<" "<<ans<<endl;        mp[x][y]=true;        mp[x-1][y]=true;        mp[x][y-1]=true;    }else if(ans==2){        cout<<x<<" "<<y-1<<" "<<ans<<endl;        mp[x][y]=true;        mp[x][y-1]=true;        mp[x-1][y-1]=true;    }else if(ans==3){        cout<<x-1<<" "<<y<<" "<<ans<<endl;        mp[x][y]=true;        mp[x-1][y-1]=true;        mp[x-1][y]=true;    }else if(ans==4){        cout<<x-1<<" "<<y-1<<" "<<ans<<endl;        mp[x-1][y-1]=true;        mp[x-1][y]=true;        mp[x][y-1]=true;    }    //print();    //cout<<isfinish()<<endl;    if(x2-x1>=2){//终止条件        dfs(x1,y1,x-1,y-1);        dfs(x1,y,x-1,y2);        dfs(x,y1,x2,y-1);        dfs(x,y,x2,y2);    }}int main(){    ios::sync_with_stdio(false);    //freopen("out.txt","w",stdout);    int x,y;    while(cin>>k>>x>>y)    {        memset(mp,false,sizeof(mp));         mp[x][y]=true;        dfs(1,1,1<<k,1<<k);    }    return 0;}
0 0
原创粉丝点击