POJ 2243 简单搜索 (DFS BFS A*)

题目大意:国际象棋给你一个起点和一个终点,按骑士的走法,从起点到终点的最少移动多少次。

求最少明显用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 }

 

posted @ 2018-01-18 14:42  demianzhang  阅读(380)  评论(0编辑  收藏  举报