B - A Knight's Journey
题目翻译
背景
这位骑士厌倦了一遍又一遍地看到相同的黑白方块,于是决定开始一段旅程世界各地。每当一个骑士移动,它是一个方向上的两个正方形和一个垂直的正方形。骑士的世界是他生活的棋盘。我们的骑士生活在一个棋盘上,它的面积比普通的8×8棋盘小,但它仍然是长方形的。你能帮助这个冒险骑士制定旅行计划吗?
问题
找到一条路,让骑士拜访每一个广场一次。骑士可以在棋盘的任何一个正方形上开始和结束。
输入
输入第一行以正整数N开头。下面几行包含N个测试用例。每个测试用例由一行包含两个正整数P和Q,例如1<=P*Q<=26。这代表了一个p*Q棋盘,其中P描述了有多少不同的平方数字1,……,P存在,Q描述了多少不同的平方字母存在。这些是拉丁字母的第一个Q字母:a,…
输出
每个场景的输出以包含“场景#I:”的行开始,其中我是从1开始的场景的数量。然后打印一个单行,包含字典的第一路径,访问所有方块的棋盘骑士与行动后一个空线。路径应该通过连接被访问的方块的名称在一条线上给出。每个方名由大写字母和数字组成。如果没有这样的路径存在,那么您应该在一行中输出不可能。
Sample Input
3
1 1
2 3
4 3
Sample Output
Scenario #1:
A1
Scenario #2:
impossible
Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4
马走日,遍历整个图,使它字典序最小,abc一个字典序,aca两个字典序,应该尽量先走上面一行,尽量走左边,这样字典序最小
bfs
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
//马走日可以走的八个方向 八个方向是有顺序的,为了得到最小字典序
int s[8][2]={{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2},{1, -2}, {1, 2}, {2, -1}, {2, 1}};
int a[1001][2],c[30][30];
int z,sum;
int n,m;//n行m列
int ss(int x,int y)
{
if(x<1||y<1||x>m||y>n)
return 0;
return 1;
}//判断是否在边界内
int bfs(int x,int y)
{
a[sum][0]=x;//0为字符
a[sum][1]=y;//1为数字
if(sum==n*m)//判断是否全部访问过
{
z=1;//全部访问做标记z
return 0;
}
int i,j;
int ii,jj;
for(i=0;i<8;i++)
{
ii=x+s[i][0];//横坐标移动 得到新的横坐标
jj=y+s[i][1];//纵坐标移动 得到新的纵坐标
if(ss(ii,jj)==1&&c[ii][jj]==0)//ss(ii,jj)==1在边界内 c[ii][jj]==0没被访问
{
c[ii][jj]=1;//访问标记
sum++;//记录访问过的格子数
bfs(ii,jj);
if(z==1) return 0;//全部访问完并有通路,结束 gg(int x,int y)=0
sum--;// 中途无通路需要返回 并消除标记
c[ii][jj]=0;//消除标记
}
}
return 1;
}
int main ()
{
int T,b=0;//b第几个案列
cin>>T;
while(T--)
{
b++; //b第几个案列
cin>>n>>m;//n行m列
memset(c,0,sizeof(c));//初始化标记
z=0;sum=1;
int i,j;
cout<<"Scenario #"<<b<<":"<<endl;//b第几个案列
char qq;
c[1][1]=1;//访问过为做标记 1
if(bfs(1,1)==0)//有通路并遍历完
for(i=1;i<=sum;i++)
{
qq=a[i][0]+64;//0为字符
cout<<qq<<a[i][1];//1为数字 先输出字符再输出数字
}else
cout<<"impossible";//没有结果
cout<<endl;//
if(T!=0)cout<<endl;//除了最后一个案例,每个案例都要换行 案例之间要有空格
}
return 0;
}