题目:
题解:
#include <iostream>
using namespace std;
int idx; //用idx记录填充数字
int a,b,length;
int cell[1024][1024];
//函数有五个参数,row_lt指的是棋盘最左上角地行坐标,col_lt指的是棋盘最左上角的列坐标
//a,b指的是特殊方格的行列坐标,lenth是棋盘的长度
void chassboard(int row_lt,int col_lt,int a,int b,int length)
{
idx ++; //每调用一次函数,idx加一
int len = length / 2;
int row_mid = row_lt + len;
int col_mid = col_lt + len;
if(length == 2) //棋盘的边长为2
{
int t = cell[a][b]; //用变量暂时保存cell[a][b]的值;
for(int i = 0;i < 2;i ++) //此时的i和j不是下标,是增量
{
for(int j = 0;j < 2;j ++)
{
cell[row_lt + i][col_lt + j] = idx;
}
}
cell[a][b] = t; //还原,因为经过上面两个循环将这个边长为2的
return; //棋盘都覆盖为idx的值
}
//将该棋盘等分为四个小棋盘,分治思想
if(a < row_mid)
{
if(b < col_mid) //特殊方格再左上方
{
//将其余三个小棋盘的交界方格填充为idx,先后顺序没关系哦
cell[row_mid - 1][col_mid] = idx;
cell[row_mid][col_mid - 1] = idx;
cell[row_mid][col_mid] = idx;
//递归,调用函数,此时要区分顺序,按照题目给定地顺序依次填充
chassboard(row_lt,col_lt,a,b,len);
chassboard(row_lt,col_mid,row_mid - 1,col_mid,len);
chassboard(row_mid,col_mid,row_mid,col_mid,len);
chassboard(row_mid,col_lt,row_mid,col_mid - 1,len);
}
else //特殊方格在右上方
{
//将其余三个小棋盘的交界方格填充为idx,先后顺序没关系哦
cell[row_mid - 1][col_mid - 1] = idx;
cell[row_mid][col_mid - 1] = idx;
cell[row_mid][col_mid] = idx;
//递归,调用函数,此时要区分顺序,按照题目给定地顺序依次填充
chassboard(row_lt,col_lt,row_mid - 1,col_mid - 1,len);
chassboard(row_lt,col_mid,a,b,len);
chassboard(row_mid,col_mid,row_mid,col_mid,len);
chassboard(row_mid,col_lt,row_mid,col_mid - 1,len);
}
}
else
{
if(b < col_mid) //特殊方格在左下方
{
//将其余三个小棋盘的交界方格填充为idx,先后顺序没关系哦
cell[row_mid - 1][col_mid - 1] = idx;
cell[row_mid - 1][col_mid] = idx;
cell[row_mid][col_mid] = idx;
//递归,调用函数,此时要区分顺序,按照题目给定地顺序依次填充
chassboard(row_lt,col_lt,row_mid - 1,col_mid - 1,len);
chassboard(row_lt,col_mid,row_mid - 1,col_mid,len);
chassboard(row_mid,col_mid,row_mid,col_mid,len);
chassboard(row_mid,col_lt,a,b,len);
}
else //特殊方格在右下方
{
//将其余三个小棋盘的交界方格填充为idx,先后顺序没关系哦
cell[row_mid - 1][col_mid - 1] = idx;
cell[row_mid - 1][col_mid] = idx;
cell[row_mid][col_mid - 1] = idx;
//递归,调用函数,此时要区分顺序,按照题目给定地顺序依次填充
chassboard(row_lt,col_lt,row_mid - 1,col_mid - 1,len);
chassboard(row_lt,col_mid,row_mid - 1,col_mid,len);
chassboard(row_mid,col_mid,a,b,len);
chassboard(row_mid,col_lt,row_mid,col_mid - 1,len);
}
}
}
int main()
{
cin>>a>>b>>length;
chassboard(1,1,a,b,length);
for(int i = 1;i <= length;i ++)
{
for(int j = 1;j <= length;j ++)
{
printf("%4d",cell[i][j]);
}
printf("\n");
}
return 0;
}
心得:
通过将一个大问题转化成若干个等价的小问题,解决小问题再合并,这就是分治
本题将棋盘细分为若干个长度为2的小棋盘,然后再对小棋盘填充,这里的idx也可以理解为函数调用的次数。
在对棋盘进行划分时,需要更新每个子棋盘的最左上角的方格的坐标、子棋盘的特殊方格及子棋盘的长度。