题目大意:给一个p,q分别代表图的行与列数(列在输出时用A,B......表示),规定一个走的规则,求出走遍所有格子且不重复的方法,若有多种答案则输出字典序最小的,无输出impossible。这里的字典序以列优先,即A2<B1。
题目链接:点击打开链接
分析:想要走遍全图很简单,这里棘手的便是要输出字典序最小的一个,由于dfs的特性,我们可以用贪心的思想来遍历,1.每次dfs的入口应该按照先枚举列再枚举行 2.每次dfs在递归时总是有8种走法,我们按照预先设定好的按字典序从小到大的方式来走 。 这样就可以做到第一次走完的是最小字典序的走法了。
直接上代码:
#include<cstdio>
#include<cstring>
using namespace std;
int p,q,kase,T;
int d[8][2]={{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}}; //必须按照此顺序
bool vis[10][10];
bool flag=1;
struct point
{
int x,y;
}prv[100]; //记录路径
void print()
{
printf("Scenario #%d:\n",kase-T);
for(int i=0;i<p*q;i++)
printf("%c%d",prv[i].y+'A'-1,prv[i].x);
printf("\n\n");
}
void dfs(int x,int y,int cur)
{
prv[cur-1].x=x;
prv[cur-1].y=y;
if(!flag) return;
if(cur==q*p)
{
flag=0;
print();
return;
}
for(int i=0;i<8;i++)
{
int fx=x+d[i][0],fy=y+d[i][1];
if(flag&&!vis[fx][fy]&&fx>=1&&fx<=p&&fy>=1&&fy<=q)
{
vis[fx][fy]=1;
dfs(fx,fy,cur+1);
vis[fx][fy]=0;
}
}
return;
}
int main()
{
scanf("%d",&T);
kase=T;
while(T--)
{
flag=1;
scanf("%d%d",&p,&q);
memset(vis,false,sizeof vis);
for(int j=1;j<=q;j++) //先枚举列
for(int i=1;i<=p;i++)
{
if(!flag) break;
vis[i][j]=1;
dfs(i,j,1);
vis[i][j]=0;
}
if(flag)
{
printf("Scenario #%d:\n",kase-T);
printf("impossible\n\n");
}
}
return 0;
}