题目大意:给一个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; }