解题思路
典型的分治问题:棋盘覆盖。
首先,需要将棋盘分割成为4个2(k-1)*2(k-1)的小棋盘。
那么公主的位置必然在这四个方格之内,其余三个方格中没有被占用的位置。要将这三个没被占用位置的子方格转化为被占用位置的子方格,可以使用一个“L”型骨牌覆盖在这三个子方格的汇合之处。如下图:
进而将原问题转化为4个较小规模的棋盘覆盖问题,递归这种分割,直至棋盘转化为1*1的棋盘。
完整代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void deal(int a,int b,int x,int y,int len)//a,b代表当前棋盘的左上角顶点,m,n代表障碍点
{
if(len==1) return ;
len>>=1;//len除以2
if(x<=a+len-1&&y<=b+len-1)//障碍点在左上角的棋盘
{
printf("%d %d 1\n",a+len,b+len);
deal(a,b,x,y,len);
deal(a,b+len,a+len-1,b+len,len);
deal(a+len,b,a+len,b+len-1,len);
deal(a+len,b+len,a+len,b+len,len);
}
else if(x<=a+len-1&&y>b+len-1)//障碍点在右上角棋盘
{
printf("%d %d 2\n",a+len,b+len-1);
deal(a,b,a+len-1,b+len-1,len);
deal(a,b+len,x,y,len);
deal(a+len,b,a+len,b+len-1,len);
deal(a+len,b+len,a+len,b+len,len);
}
else if(x>a+len-1&&y<=b+len-1)//障碍在左下角棋盘
{
printf("%d %d 3\n",a+len-1,b+len);
deal(a,b,a+len-1,b+len-1,len);
deal(a,b+len,a+len-1,b+len,len);
deal(a+len,b,x,y,len);
deal(a+len,b+len,a+len,b+len,len);
}
else{//障碍在右下角棋盘
printf("%d %d 4\n",a+len-1,b+len-1);
deal(a,b,a+len-1,b+len-1,len);
deal(a,b+len,a+len-1,b+len,len);
deal(a+len,b,a+len,b+len-1,len);
deal(a+len,b+len,x,y,len);
}
}
int main()
{
int m;
int x,y;
scanf("%d %d %d",&m,&x,&y);
m=1<<m;
deal(1,1,x,y,m);
return 0;
}