棋盘覆盖(分治)
Description
在一个2k × 2k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的棋盘上除特殊方格以外的所有方格,L型骨牌不能旋转,且任何两个L型骨牌不得重叠覆盖。
Input
第一行是一个T,表示案例数。对于每一个案例,有三个数K,X,Y分别表示在一个2^k * 2^K的棋盘中,在第X行第Y列有一个特殊方格。1 ≤ K ≤ 8
1 ≤ X, Y ≤ 2k
Output
输出这个被骨牌覆盖的棋盘,分别用a,b,c,d表示四种骨牌(分别用以下四种字符图形表示),特殊方格用*号表示。
aa bb c d
a b cc dd
具体输出见sample Output
Sample Input
2
2 1 2
1 1 1
Sample Output
c*bb
ccdb
cddd
ccdd
*d
dd
Author
陈渝林
分治思想
分治就是把一个大问题分解成几个小问题解决,再把小问题的解整合起来成为问题的解。
把2^k * 2^K 的棋盘分成四个2^k-1 * 2^K-1的小棋盘。
在特殊方块在的小棋盘外的三个棋盘交界处加上合适的骨牌,使它们也变成特殊棋盘。以此类推,每次分割都把一个问题变成四个小问题,直至棋盘规模为1。
#include<stdio.h>
#include<string.h>
#include<math.h>
int mapp[300][300];
void chessBoard(int r,int c,int x,int y,int s)///r:起始行 c:起始列
{
int ss,n;
if(s==1)
return;
ss=s/2;///切分棋盘
///判断中间的骨牌为什么型号
if(x<r+ss&&y<c+ss) n=4;///特殊格在左上角
else if(x>=r+ss&&y<c+ss) n=2;///左下角
else if(x<r+ss&&y>=c+ss) n=3;///右上角
else n=1;///右下角
if(x<r+ss&&y<c+ss)///左上角
{
chessBoard(r,c,x,y,ss);
}
else
{
mapp[r+ss-1][c+ss-1]=n;///覆盖右下角
chessBoard(r,c,r+ss-1,c+ss-1,ss);
}
if(x>=r+ss&&y<c+ss)///左下角
{
chessBoard(r+ss,c,x,y,ss);
}
else
{
mapp[r+ss][c+ss-1]=n;///覆盖右上角
chessBoard(r+ss,c,r+ss,c+ss-1,ss);
}
if(x<r+ss&&y>=c+ss)///右上角
{
chessBoard(r,c+ss,x,y,ss);
}
else
{
mapp[r+ss-1][c+ss]=n;///覆盖左下角
chessBoard(r,c+ss,r+ss-1,c+ss,ss);
}
if(x>=r+ss&&y>=c+ss)///右下角
{
chessBoard(r+ss,c+ss,x,y,ss);
}
else
{
mapp[r+ss][c+ss]=n;///覆盖左上角
chessBoard(r+ss,c+ss,r+ss,c+ss,ss);
}
}
int main()
{
int t;
scanf("%d",&t);
// cin>>t;
while(t--)
{
memset(mapp,0,sizeof(mapp));
int k,x,y;
scanf("%d %d %d",&k,&x,&y);
// cin>>k>>x>>y;
int s=pow(2,k);
chessBoard(1,1,x,y,s);
int i,j;
for(i=1;i<=s;i++)
{
for(j=1;j<=s;j++)
{
if(i==x&&j==y)
printf("*");
//cout<<"*";
else if(mapp[i][j]==1)
printf("a");
// cout<<"a";
else if(mapp[i][j]==2)
printf("b");
//cout<<"b";
else if(mapp[i][j]==3)
printf("c");
//cout<<"c";
else if(mapp[i][j]==4)
printf("d");
//cout<<"d";
}
printf("\n");
// cout<<endl;
}
}
return 0;
}
作业题,有错误欢迎指正。