【转】POJ-2243-Knight Moves:DFS || BFS || Floyd 求最短路
DFS
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int knight[8][8];// 各点到起点的最短距离 int x[8]={-2, -1, 1, 2, -2, -1, 1, 2}; int y[8]={-1, -2, -2, -1, 1, 2, 2, 1}; void DFS(int i, int j, int dis) { if(i<0||i>7||j<0||j>7||knight[i][j]<=dis) return; knight[i][j]=dis; for(int k=0; k<8; k++) DFS(i+x[k], j+y[k], dis+1); } int main() { char S1[10], S2[10]; while(cin>>S1>>S2) { memset(knight, 10, sizeof(knight));// 初始化距离较大 DFS时再更新 DFS(S1[0]-'a', S1[1]-'1', 0); printf("To get from %s to %s takes %d knight moves.\n", S1, S2, knight[S2[0]-'a'][S2[1]-'1']); } return 0; }
BFS
#include<iostream> #include<cstdio> #include<queue> using namespace std; int x[8]={-2, -1, 1, 2, -2, -1, 1, 2}; int y[8]={-1, -2, -2, -1, 1, 2, 2, 1}; struct point { int x, y; int dis; }; int main() { queue<point>que; char S1[10], S2[10]; while(cin>>S1>>S2) { while(!que.empty()) que.pop(); point p; p.x=S1[0]-'a'; p.y=S1[1]-'1'; p.dis=0; que.push(p); while(!que.empty()) { p = que.front(); que.pop(); if(p.x==S2[0]-'a' && p.y==S2[1]-'1') break; point tmp; for(int i=0; i<8; i++) { tmp.x=p.x+x[i]; tmp.y=p.y+y[i]; tmp.dis=p.dis+1; if(tmp.x<0 || tmp.x>7 || tmp.y<0 || tmp.y>7) continue; que.push(tmp); } } printf("To get from %s to %s takes %d knight moves.\n", S1, S2, p.dis); } return 0; }
Floyd
算法详解请点这里
应用于改题的思路:由于棋盘很小,而输入数据可能很大,则可以想到先打表存储每点到各点的最短路径,这样对于所有输入查表输出即可。
当然前提是从每一点出发可以到达任一点(题中有提到)
相对于DFS和BFS来说 Floyd的时间复杂度最小
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> using namespace std; void Floyd(int k[][64]) { int dx, dy;// 两点间相对距离 for(int i=0; i<64; k[i][i]=0,i++) for(int j=0; j<64; j++){ dx=abs(i/8-j/8); dy=abs(i%8-j%8); if(dx==1&&dy==2 || dx==2&&dy==1)// 骑士一步的距离 k[i][j]=k[j][i]=1; } for(int l=0; l<64; l++) for(int i=0; i<64; i++) for(int j=0; j<64; j++){ if(k[i][l]+k[l][j]<k[i][j]) k[i][j]=k[i][l]+k[l][j]; } } int main() { char S1[10], S2[10]; int knight[64][64];// 棋盘中每点到其余给点的距离 以骑士的步长为单位 memset(knight, 10, sizeof(knight));//初始化为无穷 Floyd(knight);// 打表 存储 while(cin>>S1>>S2) { int x=(S1[0]-'a')*8+S1[1]-'1'; int y=(S2[0]-'a')*8+S2[1]-'1'; // 直接查表 打印结果 printf("To get from %s to %s takes %d knight moves.\n", S1, S2, knight[x][y]); } return 0; }
总结:Floyd算法适合稠密图 即图小数据量大 而BFS适合稀疏图 即图大数据量小。