这道题是图论深搜的典型题。初做此题,首先觉得应当有一个邻接矩阵,于是花了很大力气将棋盘编号,最后在判断是否邻接的条件处纠结许久。
之后的搜索使用了C++的栈结构,没有使用递归(优点),但最后无论时间、代码长度、还是空间都不理想。经过学习网上大牛们的代码后,恍然
大悟,原来根本不需要构建邻接矩阵,只能说我学的太死了,完全可以使用二维数组直接模拟马的跳跃,这样判断邻接的问题就没有了。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#include <string.h>
using namespace std;
int main()
{
char board[26][26];
int num = 0;
scanf("%d",&num);
for(int i = 1;i <= num;i++)
{
int xMax,yMax;
scanf("%d %d",&xMax,&yMax);
//printf("%d %d",xMax,yMax);
memset(board,0,sizeof(board));
int boardSize = xMax * yMax;
for(int j = 0;j < boardSize;j++)
{
if((j + xMax + 2) < boardSize && ((j % xMax + 2) < xMax))
board[j][(j + xMax + 2)] = 1;
if((j + xMax - 2) < boardSize && (j + xMax - 2) >= 0 && (j % xMax - 2) >= 0)
board[j][(j + xMax - 2)] = 1;
if((j - xMax + 2) < boardSize && (j - xMax + 2) >= 0 && (j % xMax + 2) < xMax)
board[j][(j - xMax + 2)] = 1;
if((j - xMax - 2) >= 0 && (j % xMax - 2) >= 0)
board[j][(j - xMax - 2)] = 1;
if((j + 2 * xMax + 1) < boardSize && (j % xMax + 1) < xMax)
board[j][(j + 2 * xMax + 1)] = 1;
if((j + 2 * xMax - 1) < boardSize && (j + 2 * xMax - 1) >= 0 && (j % xMax - 1) >= 0)
board[j][(j + 2 * xMax - 1)] = 1;
if((j - 2 * xMax + 1) < boardSize && (j - 2 * xMax + 1) >= 0 && (j % xMax + 1) < xMax)
board[j][(j - 2 * xMax + 1)] = 1;
if((j - 2 * xMax - 1) >= 0 && (j % xMax - 1) >= 0)
board[j][(j - 2 * xMax - 1)] = 1;
}
char visited[26];
memset(visited,0,sizeof(visited));
bool flag = false;
for(int k = 0;k < boardSize;k++)
{
memset(visited,0,sizeof(visited));
stack<int> s;
s.push(k);
visited[k] = 1;
int startFrom = 0;
int record[26];
memset(record,0,sizeof(record));
int recordNum = 1;
flag = false;
if(boardSize == 1)
{
flag = true;
printf("Scenario #%d:\nA1\n\n",i);
break;
}
while(!s.empty())
{
int current = s.top();
int j;
for(j = startFrom;j < boardSize;j++)
{
if((board[current][j] == 1) && visited[j] == 0)
{
s.push(j);
visited[j] = 1;
startFrom = 0;
record[recordNum] = j;
recordNum++;
if(recordNum == boardSize)
flag = true;
break;
}
}
if(flag)
break;
if(j == boardSize)
{
startFrom = s.top() + 1;
visited[startFrom - 1] = 0;
s.pop();
recordNum--;
}
}
if(flag)
{
printf("Scenario #%d:\n",i);
for(int j = 0;j < recordNum;j++)
printf("%c%d",record[j] / xMax + 'A',record[j] % xMax + 1);
printf("\n\n");
break;
}
}
if(!flag)
printf("Scenario #%d:\nimpossible\n\n",i);
}
return 0;
}
阅读过带给我改进灵感的代码:
#include <iostream>
using namespace std;
int step[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
int main()
{
int a,b,ch[26][26],ss[26*26][3],s,p,x,y,j,xx,yy,ci=0;
cin>>a;
while(cin>>b>>a)
{
memset(ch,0,sizeof(ch));
p=a*b-1;
s=0;
ch[0][0]=1;//visit
x=0;
y=0;
j=0;
while(s>=0)
{
if (j<8)
for (;j<8;j++)
{
xx=x+step[j][0];
yy=y+step[j][1];
if (ch[xx][yy]==0 && xx>=0 && xx<a && yy>=0 && yy<b)
{
ss[s][0]=x+65;
x=xx;
ss[s][1]=y+1;
y=yy;
ss[s][2]=j;
s++;
ch[xx][yy]=1;
j=0;
break;
}
}
if (s==p)
break;
if (j==8)
{
s--;
if (s>=0)
{
ch[x][y]=0;
x=ss[s][0]-65;
y=ss[s][1]-1;
j=ss[s][2]+1;
}
}
}
++ci;
printf("Scenario #%d:\n",ci);
if (s==p)
{
for (p=0;p<s;p++)
cout<<char(ss[p][0])<<ss[p][1];
x+=65;
cout<<char(x)<<y+1;
}
else
cout<<"impossible";
cout<<endl<<endl;
}
return 0;
}