Description
相传在一个古老的阿拉伯国家里,有一座宫殿。宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站立的地方外的所有地方盖上,美丽漂亮聪慧的公主就是他的人了。公主这一个方格不能用地毯盖住,毯子的形状有所规定,只能有四种选择(如下图所示):
并且每一方格只能用一层地毯,迷宫的大小为(2^K)^2的方形。当然,也不能让公主无限制的在那儿等,对吧?由于你使用的是计算机,所以实现时间为ls。
Input
第一行:k,即给定被填补迷宫的大小为(2^K)^2
第二行:x y,即给出公主所在方格的坐标(x为行坐标,y为列坐标),x和y之间有一个空格隔开。
Output
将迷宫填补完整的方案:每一补(行)为x y c(x,y为毯子左上角的行坐标和列坐标,c为使用毯子的形状,具体见上面的图,毯子形状分别用1、2、3、4表示,x、y、c之问用一个空格隔开)。按x,y,c的字典序输出。
Sample Input
2
3 3
Sample Output
1 1 4
1 3 2
2 2 4
3 1 1
3 3 3
Hint
分治
solution
本题的棋盘是2^k*2^k的,很容易想到分治:把棋盘切为四块,则每一块都是2^(k-1)*2^(k-1)的。有黑格的那一块可以递归解决,但其他3块并没有黑格子,应该怎么办呢?可以构造出一个黑格子,如图所示。递归边界也不难得出:k=1时一块牌就够了。
□□□□|□□□□
□■□□|□□□□
□□□□|□□□□
□□□□|◆□□□
————————-
□□□◆|◆□□□
□□□□|□□□□
□□□□|□□□□
□□□□|□□□□
原来的特殊方格用■表示,构造的特殊方格用◆表示
- 代码
#include <cstdio>
#include <cstdlib>
using namespace std;
int title = 1, size, sk = 1;
int board[2049][2049], x, y;
int t[4], br[2049][2049], ar[4][3], ok;
const int d[5][2] ={
0,0,-1,0,1,0,0,1,0,-1
};
void chessboard(int tr, int tc, int dr, int dc, int size)//分治过程
//dc,dr表示特殊方格的坐标,tr,tr表示区域左上角的坐标,size表示当前棋盘大小
{
if(size == 1) return;
int t = title; //t表示填充L型骨牌的数字,title初始为1
title++;
int s = size / 2; //将棋盘四等分
if(dr <= tr + s - 1 && dc < tc + s) //特殊格子在左上角
chessboard(tr, tc, dr, dc, s);
else {
//特殊方格不在左上区域内,设置左上区域的右下角方格为特殊方格,用t填充
board[tr + s - 1][tc + s - 1] = t;
chessboard(tr, tc, tr + s - 1, tc + s -1, s);
}
if(dr < tr + s && dc >= tc + s) //特殊格子在右上区域内
chessboard(tr, tc + s, dr, dc, s);
else {
//特殊方格不在右上区域内,设置右上区域的最左下角方格为特殊方格,用t填充
board[tr + s - 1][tc + s] = t;
chessboard(tr, tc + s,tr + s - 1, tc + s, s);
}
if(dr >= tr + s && dc < tc + s) //特殊格子不在在左下区域
chessboard(tr + s, tc, dr, dc, s);
else {
//特殊方格不在左下区域类内,设置左下区域的最右上角为特殊方格,用t填充
board[tr + s][tc + s - 1] = t;
chessboard(tr + s, tc, tr + s, tc + s - 1, s);
}
if(dr >= tr + s && dc >= tc + s) //特殊格子在右下区域
chessboard(tr + s, tc + s, dr, dc, s);
else {
//特殊方格不在右下区域内,设置右下区域的最左上角为特殊方格,用t填充
board[tr + s][tc + s] = t;
chessboard(tr + s, tc + s, tr + s, tc + s, s);
}
}
int judge1()
{
ar[2][1] = ar[1][1] + 1;
ar[2][2] = ar[1][2];
ar[3][1] = ar[2][1];
ar[3][2] = ar[2][2] + 1;
if(board[ar[2][1]][ar[2][2]] == board[ar[1][1]][ar[1][2]]
&&board[ar[3][1]][ar[3][2]] == board[ar[1][1]][ar[1][2]])
return 1;
return 0;
}
int judge2()
{
ar[2][1] = ar[1][1];
ar[2][2] = ar[1][2] + 1;
ar[3][1] = ar[2][1] + 1;
ar[3][2] = ar[2][2];
if(board[ar[2][1]][ar[2][2]] == board[ar[1][1]][ar[1][2]]
&&board[ar[3][1]][ar[3][2]] == board[ar[1][1]][ar[1][2]])
return 1;
return 0;
}
int judge3()
{
ar[2][1] = ar[1][1] + 1;
ar[2][2] = ar[1][2];
ar[3][1] = ar[2][1];
ar[3][2] = ar[2][2] - 1;
if(board[ar[2][1]][ar[2][2]] == board[ar[1][1]][ar[1][2]]
&&board[ar[3][1]][ar[3][2]] == board[ar[1][1]][ar[1][2]])
return 1;
return 0;
}
int judge4()
{
ar[2][1] = ar[1][1];
ar[2][2] = ar[1][2] + 1;
ar[3][1] = ar[1][1] + 1;
ar[3][2] = ar[1][2];
if(board[ar[2][1]][ar[2][2]] == board[ar[1][1]][ar[1][2]]
&&board[ar[3][1]][ar[3][2]] == board[ar[1][1]][ar[1][2]])
return 1;
return 0;
}
void dfs(int i, int a, int b) //判读格子类型
{
if(1) {
if(judge1()) {
t[1] = ar[1][1];
t[2] = ar[1][2];
t[3] = 1;
br[ar[2][1]][ar[2][2]] = 1;
br[ar[3][1]][ar[3][2]] = 1;
}
else if(judge2()) {
t[1] = ar[1][1];
t[2] = ar[1][2];
t[3] = 2;
br[ar[2][1]][ar[2][2]] = 1;
br[ar[3][1]][ar[3][2]] = 1;
}else if(judge3()) {
t[1] = ar[1][1];
t[2] = ar[3][2];
t[3] = 3;
br[ar[2][1]][ar[2][2]] = 1;
br[ar[3][1]][ar[3][2]] = 1;
}else if(judge4()){
t[1] = ar[1][1];
t[2] = ar[1][2];
t[3] = 4;
br[ar[2][1]][ar[2][2]] = 1;
br[ar[3][1]][ar[3][2]] = 1;
}
return;
}
}
int main()
{
int i, j;
scanf("%d", &size);
for(i = 1; i <= size; i++)
sk *= 2;
scanf("%d%d", &x, &y);
chessboard(1, 1, x, y, sk);
for(i = 1; i <= sk; i++)
for(j = 1; j <= sk; j++)
if(!br[i][j] && board[i][j]) {
ok = 0;
ar[1][1] = i; ar[1][2] = j;
br[i][j] = 1;
dfs(2, i, j);
printf("%d %d %d\n", t[1], t[2], t[3]);
}
return 0;
}
注:本程序只能在校内测试网站通过,如果读者想通过codevs1496还需自行编写代码(主要因为地毯输出顺序的问题)