题目
棋盘覆盖问题。
有一个
2k∗2k
2
k
∗
2
k
的方格棋盘,恰有一个方格是黑色的,其他为白色。你的任务是用包含3个方格的L型牌覆盖所有白色方格。黑色方格不能被覆盖,且任意一个白色方格不能同时被两个或更多牌覆盖。如图所示为L型牌的4种旋转方式。
代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
const int maxn = 3000;
int k, x, y, cnt = 0, ans[maxn][maxn];
int getnum(int x, int y, int d){
int n = pow(2, d)/2;
if (x < n && y < n) return 0;
else if (x > n && y > n) return 3;
else if (x < n && y > n) return 2;
else if (x > n && y < n) return 1;
}
void solve(int d, int x, int r, int c){
cnt++;
if (x != 0) ans[r+(int)pow(2,d-1)-1][c+(int)pow(2,d-1)-1] = cnt;
if (x != 1) ans[r+(int)pow(2,d-1)-1][c+(int)pow(2,d-1)] = cnt;
if (x != 2) ans[r+(int)pow(2,d-1)][c+(int)pow(2,d-1)-1] = cnt;
if (x != 3) ans[r+(int)pow(2,d-1)][c+(int)pow(2,d-1)] = cnt;
if (d > 1){
if (x != 0) solve(d-1, 3, r, c);
else solve(d-1, getnum(x, y, d-1), r, c);
if (x != 1) solve(d-1, 2, r, c+pow(2, d-1));
else solve(d-1, getnum(x, y, d-1), r, c+pow(2, d-1));
if (x != 2) solve(d-1, 1, r+pow(2,d-1), c);
else solve(d-1, getnum(x, y, d-1), r+pow(2,d-1), c);
if (x != 3) solve(d-1, 0, r+pow(2,d-1), c+pow(2,d-1));
else solve(d-1, getnum(x, y, d-1), r+pow(2,d-1), c+pow(2,d-1));
}
}
int main(){
scanf("%d%d%d", &k, &x, &y);
solve(k, getnum(x,y,k), 0, 0);
for (int i = 0; i<pow(2,k); i++){
for (int j = 0; j<pow(2,k); j++)
printf("%d ",ans[i][j]);
printf("\n");
}
return 0;
}
其他话
- 代码好乱。。但是比较短还差不多。
- 这道题思路好想,但代码实现有点麻烦。这道题光想就想了一下午。。。
3.大体思路:分治访问每个正方形的四个小方块,各自求解。对于有题给小方块的方块,必然有解。其它的,每个出一个还能凑三个,正好一个图形。所以就假设每个小方块都有个黑块,其中一个是题目给的,其它是靠向图中心的。