题目地址
AC代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int list[27][27],ans[27][27];
bool tell(int x,int y){
for (int i = 1; i <= y; ++i) {
for (int j = 1; j <= x; ++j) {
if(list[i][j]==0)return false;
}
}
return true;
}
void cmp(int x,int y){
int max1 = 0,max2=0;
for (int i = 1; i <= y; ++i) {
for (int j = 1; j <= x; ++j) {
if(list[i][j]>max1)max1=list[i][j];
if(ans[i][j]>max2)max2=ans[i][j];
}
}
pair<int,int>a,b;
b.first=99,b.second=99;
for (int k = 1; k <= max(max1,max2); ++k) {
for (int i = 1; i <= y; ++i) {
for (int j = 1; j <= x; ++j) {
if(list[i][j]==k)a.first=i,a.second=j;
if(ans[i][j]==k)b.first=i,b.second=j;
}
}
if(a.first<b.first){
memcpy(ans,list, sizeof(list));
return;
}else if(a.first>b.first)return;
if(a.second<b.second){
memcpy(ans,list, sizeof(list));
return;
}else if(a.second>b.second)return;
}
}
void dfs(int x,int y,int counter,int sizeY,int sizeX){
list[y][x]=counter;
if(tell(sizeX,sizeY)){
cmp(sizeX,sizeY);
list[y][x]=0;
return;
}
if(y+2>=1&&y+2<=sizeY&&x+1>=1&&x+1<=sizeX&&list[y+2][x+1]==0)dfs(x+1,y+2,counter+1,sizeY,sizeX);
if(y+2>=1&&y+2<=sizeY&&x-1>=1&&x-1<=sizeX&&list[y+2][x-1]==0)dfs(x-1,y+2,counter+1,sizeY,sizeX);
if(y-2>=1&&y-2<=sizeY&&x+1>=1&&x+1<=sizeX&&list[y-2][x+1]==0)dfs(x+1,y-2,counter+1,sizeY,sizeX);
if(y-2>=1&&y-2<=sizeY&&x-1>=1&&x-1<=sizeX&&list[y-2][x-1]==0)dfs(x-1,y-2,counter+1,sizeY,sizeX);
if(y+1>=1&&y+1<=sizeY&&x+2>=1&&x+2<=sizeX&&list[y+1][x+2]==0)dfs(x+2,y+1,counter+1,sizeY,sizeX);
if(y+1>=1&&y+1<=sizeY&&x-2>=1&&x-2<=sizeX&&list[y+1][x-2]==0)dfs(x-2,y+1,counter+1,sizeY,sizeX);
if(y-1>=1&&y-1<=sizeY&&x+2>=1&&x+2<=sizeX&&list[y-1][x+2]==0)dfs(x+2,y-1,counter+1,sizeY,sizeX);
if(y-1>=1&&y-1<=sizeY&&x-2>=1&&x-2<=sizeX&&list[y-1][x-2]==0)dfs(x-2,y-1,counter+1,sizeY,sizeX);
list[y][x]=0;
}
void ou(int x,int y,int counter){
cout<<"Scenario #"<<counter<<":"<<endl;
for (int i = 1; i <=x*y; ++i) {
int boo = 0;
for (int j = 1; j <= y; ++j) {
for (int k = 1; k <= x; ++k) {
if(ans[j][k]==i){
boo = 1;
char xx = j+'A'-1;
cout<<xx<<k;
break;
}
}
if(boo)break;
}
if(!boo){
cout<<"impossible";
break;
}
}
cout<<endl<<endl;
}
int main() {
ios::sync_with_stdio(false);
int n;
cin>>n;
for (int i = 1; i <=n; ++i) {
int x,y;
cin>>x>>y;
memset(list,0, sizeof(list));
memset(ans,0,sizeof(ans));
dfs(1,1,1,y,x);
ou(x,y,i);
}
return 0;
}
题解和题目思路
这道题可以分为两部分来做
首先判断是否存在一种路径,使得其能够被一次性遍历完
其次判断如果存在多种路径,哪一种路径是字典序最小的
判断是否存在路径,用DFS遍历所有可能的走法即可,每一次DFS都将当前的步数编号记录在LIST当中,并且判断棋盘是否已经全部走完
不管走完没走完,最重要的是重置当前节点的状态(走过了->没走过),如果忽略了这一步操作(尤其是在走完最后一步之后)都会导致DFS要么直接递回结束,要么就是出错
至于怎么比较ans和list数组中存储的结果,我们将比较字典序的问题转化为按顺序比较每一个元素的坐标大小问题即可,即将形如"A1"这样子的坐标转化为(1,1)这样的坐标,然后按顺序比较两个坐标之间X、Y的大小即可。