简单搜索,我这里用的是dfs,由于棋盘只有8x8这么大,于是想到dfs应该可以过,后来由于边界的问题,TLE了,改了边界才AC。
这道题的收获就是知道了有些时候dfs没有特定的边界的时候要自己设置一个合适的边界。这题推导可知,任意两点之间马踩6步之内一定能够到达,6步之内还未搜到说明绝对不是最优结果,果断退出。所以这里的res开始时最小设定为6即可,随着设的res的增大,运行时间越来越多,因为深搜可以有很多的分支,不采取较小的边界的话,可能会浪费很多时间在无用的搜索上,所以需要如此剪枝。
反复提交验证发现,res设不同值的运行时间如下:
res = 6 102ms
res = 10 222ms
res = 20 429ms
res = 30 929ms (过了30后极速增长)
res = 31 1692ms
res = 32 TLE !!!
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 9 int vis[N][N]; int res; int dx[8] = {1,1,-1,-1,2,2,-2,-2}; int dy[8] = {2,-2,2,-2,1,-1,1,-1}; inline bool OK(int nx,int ny) { if(nx >= 1 && nx <=8 && ny >= 1 && ny <= 8 && !vis[nx][ny]) return true; return false; } void dfs(int sx,int sy,int tx,int ty,int cnt) { if(cnt >= res) return; if(sx == tx && sy == ty && cnt < res) { res = cnt; return; } for(int i=0;i<8;i++) { int nx = sx + dx[i]; int ny = sy + dy[i]; if(!OK(nx,ny)) continue; vis[nx][ny] = 1; dfs(nx,ny,tx,ty,cnt+1); vis[nx][ny] = 0; } return; } int main() { char s1[4],s2[4]; int sx,sy,tx,ty; while(scanf("%s%s",s1,s2)!=EOF) { sx = s1[0] - 'a' + 1; tx = s2[0] - 'a' + 1; sy = s1[1] - '0'; ty = s2[1] - '0'; memset(vis,0,sizeof(vis)); vis[sx][sy] = 1; res = 6; //·dfs边界,能取到正确的最小值最好,这里设为6或以上即可 dfs(sx,sy,tx,ty,0); printf("To get from %s to %s takes %d knight moves. ",s1,s2,res); } return 0; }