zoukankan      html  css  js  c++  java
  • 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.
    ",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.
    ",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.
    ",line[0],line[1],line[3],line[4],ans);
    83     }
    84 
    85     return 0;
    86 }
  • 相关阅读:
    iOS API 概述
    iOS开发的一些奇巧淫技3
    iOS开发的一些奇巧淫技1&2
    iOS-一键拨号
    iOS层次架构
    简单block 和 代理
    iOS开发-单例GCD
    简单的归档、接档
    通知中心与本地通知
    安装linux centos 7.7 遇到 DRM:Pointer to TMDS table invalid
  • 原文地址:https://www.cnblogs.com/demian/p/8310180.html
Copyright © 2011-2022 走看看