题目大意:国际象棋给你一个起点和一个终点,按骑士的走法,从起点到终点的最少移动多少次。
求最少明显用bfs,下面给出三种搜索算法程序:
1 // BFS 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 const int maxn=10; 7 int r1,c1,r2,c2; 8 struct Node 9 { 10 int r,c; 11 Node(int r,int c):r(r),c(c){} 12 }; 13 int vis[maxn][maxn]; 14 int dist[maxn][maxn]; 15 queue<Node> Q; 16 int dr[]={-2,-2,-1,-1,1,1,2,2}; 17 int dc[]={-1,1,2,-2,2,-2,1,-1}; 18 int BFS() 19 { 20 if(r1==r2&&c1==c2) return 0; 21 while(!Q.empty()) Q.pop(); 22 memset(vis,0,sizeof(vis)); 23 vis[r1][c1]=1; 24 dist[r1][c1]=0; 25 Q.push(Node(r1,c1)); 26 while(!Q.empty()) 27 { 28 Node node=Q.front();Q.pop(); 29 int r=node.r,c=node.c; 30 for(int d=0;d<8;d++) 31 { 32 int nr=r+dr[d]; 33 int nc=c+dc[d]; 34 if(nr>=0&&nr<8 && nc>=0 &&nc<8 &&vis[nr][nc]==0) 35 { 36 if(nr==r2&&nc==c2) return dist[r][c]+1; 37 dist[nr][nc]=1+dist[r][c]; 38 Q.push(Node(nr,nc)); 39 vis[nr][nc]=1; 40 } 41 } 42 } 43 return -1; 44 } 45 int main() 46 { 47 char str1[10],str2[10]; 48 while(scanf("%s%s",str1,str2)==2) 49 { 50 r1=str1[1]-‘1‘; 51 c1=str1[0]-‘a‘; 52 r2=str2[1]-‘1‘; 53 c2=str2[0]-‘a‘; 54 printf("To get from %s to %s takes %d knight moves.\n",str1,str2,BFS()); 55 } 56 return 0; 57 }
DFS:
注意visited结点,如果步数较小也继续搜索
1 // DFS 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 const int maxn=10; 7 int r1,c1,r2,c2; 8 struct Node 9 { 10 int r,c; 11 Node(int r,int c):r(r),c(c){} 12 }; 13 int vis[maxn][maxn]; 14 int dist[maxn][maxn]; 15 int dr[]={-2,-2,-1,-1,1,1,2,2}; 16 int dc[]={-1,1,2,-2,2,-2,1,-1}; 17 int ans;//最终答案 18 void DFS(int r,int c,int len) 19 { 20 if(ans<=len || r<0 || r>=8 || c<0 || c>=8) return ;//剪枝 21 if(r==r2&&c==c2) ans=min(ans,len); 22 if(vis[r][c]==0 || dist[r][c]>len) 23 { 24 vis[r][c]=1; 25 dist[r][c]=len; 26 } 27 else if(vis[r][c]==1 && len >= dist[r][c] ) 28 return ; 29 for(int d=0;d<8;d++) 30 { 31 int nr=r+dr[d]; 32 int nc=c+dc[d]; 33 DFS(nr,nc,len+1); 34 } 35 } 36 int main() 37 { 38 char str1[10],str2[10]; 39 while(scanf("%s%s",str1,str2)==2) 40 { 41 r1=str1[1]-‘1‘; 42 c1=str1[0]-‘a‘; 43 r2=str2[1]-‘1‘; 44 c2=str2[0]-‘a‘; 45 memset(vis,0,sizeof(vis)); 46 ans=10; 47 DFS(r1,c1,0); 48 printf("To get from %s to %s takes %d knight moves.\n",str1,str2,ans); 49 } 50 return 0; 51 }
A*算法:
g函数为沿路径从起点到当前点的移动耗费(经过的步数),启发函数h为当前格子到终点横坐标差与纵坐标差的和(曼哈顿距离),用优先队列保存每个状态按照g+h排序。通常,我们令水平或者垂直移动的耗费为10,对角线方向耗费为14。取这些值是因为沿对角线的距离是沿水平或垂直移动耗费的的根号2,或者约1.414倍。为了简化,可以用10和14近似。
bfs
1 #include <cstring> 2 #include <iostream> 3 #include <cmath> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <cstdio> 8 9 using namespace std; 10 11 const int maxn = 10; 12 13 struct Node{ 14 int x,y,step; 15 int f,g,h; 16 // g函数为走到当前状态的经过的步数,启发函数h为当前格子到终点横坐标差与纵坐标差的和,用优先队列保存每个状态按照g+h排序 17 bool operator < (const Node & tmp) const{ 18 return f > tmp.f; 19 } 20 }node; 21 22 bool visd[maxn][maxn]; 23 priority_queue<Node> Que; 24 int dirs[8][2]={{-2,-1},{-2,1},{2,-1},{2,1},{-1,-2},{-1,2},{1,-2},{1,2}}; 25 int start_x,start_y,end_x,end_y,ans; 26 27 bool isIN(int x,int y) 28 { 29 if(x>=8||x<0)return false; 30 if(y>=8||y<0)return false; 31 return true; 32 } 33 void init() 34 { 35 memset(visd,false,sizeof(visd)); 36 while(!Que.empty())Que.pop(); 37 Node S; 38 S.x=start_x;S.y=start_y; 39 S.step=0;S.g=0;S.h=(abs(end_x-start_x)+abs(end_y-start_y))*10; 40 S.f=S.g+S.h; 41 visd[S.x][S.y]=true; 42 Que.push(S); 43 ans=-1; 44 } 45 46 void Astar() 47 { 48 Node A,B; 49 while(!Que.empty()) 50 { 51 A=Que.top();Que.pop(); 52 if(A.x==end_x&&A.y==end_y) 53 { 54 ans=A.step; 55 break; 56 } 57 for(int i=0;i<8;i++) 58 { 59 int xx=dirs[i][0]+A.x; 60 int yy=dirs[i][1]+A.y; 61 if(isIN(xx,yy)==false||visd[xx][yy])continue; 62 B.x=xx;B.y=yy; 63 B.step=A.step+1; 64 B.g=A.g+23; 65 B.h=(abs(end_y-yy)+abs(end_x-xx))*10; 66 B.f=B.g+B.h; 67 visd[B.x][B.y]=true; 68 Que.push(B); 69 } 70 } 71 } 72 73 int main() 74 { 75 char line[10]; 76 while(gets(line)) 77 { 78 start_x=line[0]-‘a‘;start_y=line[1]-‘1‘; 79 end_x=line[3]-‘a‘;end_y=line[4]-‘1‘; 80 init(); 81 Astar(); 82 printf("To get from %c%c to %c%c takes %d knight moves.\n",line[0],line[1],line[3],line[4],ans); 83 } 84 85 return 0; 86 }