G - Find a way (BFS+DFS)题解

老样子,题目优先:

【Here】

Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year, yifenfei have many people to meet. Especially a good friend Merceki. 
Yifenfei’s home is at the countryside, but Merceki’s home is in the center of city. So yifenfei made arrangements with Merceki to meet at a KFC. There are many KFC in Ningbo, they want to choose one that let the total time to it be most smallest. 
Now give you a Ningbo map, Both yifenfei and Merceki can move up, down ,left, right to the adjacent road by cost 11 minutes. 

Input

The input contains multiple test cases. 
Each test case include, first two integers n, m. (2<=n,m<=200). 
Next n lines, each line included m character. 
‘Y’ express yifenfei initial position. 
‘M’    express Merceki initial position. 
‘#’ forbid road; 
‘.’ Road. 
‘@’ KCF 
Output

For each test case output the minimum total time that both yifenfei and Merceki to arrival one of KFC.You may sure there is always have a KFC that can let them meet.

【热心翻译】

经过一年在杭州的学习,叶芬菲终于来到家乡宁波。离开宁波一年,叶芬飞有很多人要见。尤其是一个好朋友Merceki。伊芬菲的家在乡下,梅塞基的家在市中心。于是伊芬飞和梅塞基安排在肯德基见面。宁波有很多肯德基,他们想选择一个让肯德基的总时间最小的肯德基。

现在给你一张宁波地图,叶芬飞和梅塞基都可以上上下下,左移,右移到相邻的公路,花费11分钟。

输入

包含多个测试用例。每个测试用例包括,前两个整数n,m.(2<=n,m<=200)。下n行,每一行包含m个字符。

“Y”表示“Yifenfi”的起始位置。

"M"表示Merceki的初始位置。

“#"禁止走的路;

".”公路。

"@"KCF。

输出

都是Yifenfi和Merceki到达KFC的最小总时间。您可以肯定,总有一个肯德基可以让他们见面。

Sample Input

4 4
Y.#@
....
.#..
@..M
4 4
Y.#@
....
.#..
@#.M
5 5
Y..@.
.#...
.#...
@..M.
#...#

Sample Output

66
88
66

【分析一下】

1.概述:地图搜索两人相遇在限定地点的最短时间。

2.由于是两人搜索,所以记录时间可以把常规的vis数组改为三维数组来分别记录。

【评评理嘛】

1.实践证明:这类题数据偏大的情况,BFS在速度方面明显优于DFS,即使BFS多一个遍历找最小时间,不管DFS怎么优化(反正我是不行了)。

2.写了3个代码版本,分别是BFS,DFS,DFS调试代码(留有修改的地方,也算是易错点吧,如果对这类题的DFS做法原理不太了解的可以学习一下)。

3.另外,本题DFS算法会TLE(超时),不过答案正确,还是有可学习之处,易错点也没什么的,BFS也就那样的模板,DFS做法易错的都在第三个代码里面写了。

4.DFS调试代码自行操作,哪部分不懂,输出哪部分就是了。(windows.h是调用Sleep需要的头文件)

【代码专区】

复制代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std; 
int n,m;
char mp[209][209];
int vis[209][209][2];
int f[4]={1,0,-1,0};
int g[4]={0,1,0,-1};
struct ii
{
    int x,y;
}Y,M;
void BFS(ii now,int z)
{
    queue<ii>p;
    p.push(now);
    while(p.size())
    {
        ii w=p.front();
        p.pop();
        for(int i=0;i<4;++i)
        {
            int x=w.x+f[i];
            int y=w.y+g[i];
            if(!vis[x][y][z]&&mp[x][y]!='#'&&x>0&&x<=n&&y>0&&y<=m)
            {
                vis[x][y][z]=vis[w.x][w.y][z]+1;
                p.push({x,y});
            }
        }
    }
}
int main()
{
    while(cin>>n>>m)
    {
        memset(vis,0,sizeof vis);
        int i,k;
        queue<ii>p;
        for(i=1;i<=n;++i)
        for(k=1;k<=m;++k)
        {
            cin>>mp[i][k];
            if(mp[i][k]=='Y')Y.x=i,Y.y=k;
            if(mp[i][k]=='M')M.x=i,M.y=k;
            if(mp[i][k]=='@')p.push({i,k});
        }
        BFS(Y,1);
        BFS(M,0);
        int mi=99999999;
        while(p.size())
        {
            ii w=p.front();
            p.pop();
            if(vis[w.x][w.y][0]&&vis[w.x][w.y][1])
            mi=min(mi,vis[w.x][w.y][0]+vis[w.x][w.y][1]);
        }
        cout<<mi*11<<endl;
    }
    return 0;
}
AC的BFS
复制代码
复制代码
 1 #include<cstdio>
 2 int n,m,mine,sum;
 3 int YX,YY,MX,MY;
 4 char mp[201][201];
 5 int vis[201][201][2];
 6 int f[] ={1,0,-1,0},g[] ={0,1,0,-1};
 7 int check(int x,int xx,int y,int yy,int z)
 8 {
 9     if(vis[xx][yy][z]!=0&&vis[xx][yy][z]>vis[x][y][z]+1)return 1;
10     else return 0;
11 }
12 void dfs(int x,int y,int z)
13 {
14     for(int xx,yy,i=0;i<4;i++)
15     {
16         xx=x+f[i];
17         yy=y+g[i];
18         if((!vis[xx][yy][z]||check(x,xx,y,yy,z))&&(mp[xx][yy]!='#'&&xx>=0&&xx<n&&yy>=0&&yy<m))
19         {
20             vis[xx][yy][z]=vis[x][y][z]+1;
21             dfs(xx,yy,z);
22             if(z&&mp[xx][yy]=='@')
23             {
24                 sum=vis[xx][yy][1]+vis[xx][yy][0];
25                 if((mine>sum&&mine)||!mine)mine=sum;
26             }
27             vis[YX][YY][0]=0;
28             vis[MX][MY][1]=0;
29         }
30     }
31 }
32 int main()
33 {
34     while(~scanf("%d %d ",&n,&m))
35     {
36         mine=0;
37         char p;
38         for(int i=0;i<n;i++)
39         {
40             for(int k=0;k<m;k++)
41             {
42                 scanf("%c",&p);
43                 mp[i][k]=p;
44                 vis[i][k][0]=0;vis[i][k][1]=0;
45                 if(p=='Y')YX=i,YY=k;
46                 if(p=='M')MX=i,MY=k;
47                 if(p=='#')vis[i][k][0]=1,vis[i][k][1]=1;
48             }
49             getchar();
50         }
51         dfs(YX,YY,0);
52         dfs(MX,MY,1);
53         printf("%d\n",mine*11);
54     }
55     return 0;
56 }
答案正确但是超时的DFS
复制代码
复制代码
  1 #include<iostream>
  2 #include<windows.h>
  3 using namespace std;
  4 int n,m,mine,sum;int yx,yyy,mx,my;
  5 char mp[201][201];
  6 int vis[201][201][2];
  7 int f[] ={1,0,-1,0},g[] ={0,1,0,-1};
  8 int check1(int x,int y,int z)
  9 {
 10     if(vis[x][y][z]==0&&mp[x][y]!='#'&&x>=0&&x<n&&y>=0&&y<m)
 11     {
 12         //cout<<"通过条件1"<<endl;
 13         return 1;//失误1:忘写x,y限定范围条件 
 14     }
 15     else return 0;
 16 }
 17 int check2(int x,int xx,int y,int yy,int z)
 18 {
 19     if(vis[xx][yy][z]!=0&&vis[xx][yy][z]>vis[x][y][z]+1&&mp[xx][yy]!='#'&&xx>=0&&xx<n&&yy>=0&&yy<m)//失误2:变化条件写反,无限优化循环 
 20     {
 21         cout<<mp[x][y]<<" , "<<mp[xx][yy]<<endl;
 22         Sleep(500);
 23         cout<<"耗时" <<vis[xx][yy][z]<<"--->>>"<<vis[x][y][z]+1<<"坐标("<<xx<<""<<yy<<")被优化"<<endl;
 24         //cout<<"通过条件   2"<<endl;
 25         return 1;
 26     }
 27     else return 0;
 28 }
 29 void dfs(int x,int y,int z)
 30 {
 31     //cout<<"坐标("<<x<<","<<y<<")"<<endl;
 32     for(int xx,yy,i=0;i<4;i++)
 33     {
 34         xx=x+f[i];
 35         yy=y+g[i];
 36         if(check1(xx,yy,z)||check2(x,xx,y,yy,z))
 37         {
 38             vis[xx][yy][z]=vis[x][y][z]+1;
 39             dfs(xx,yy,z);
 40             if(mp[xx][yy]=='@')
 41             {
 42                 if(z)
 43                 cout<<"M找到@,耗时" <<vis[xx][yy][z]<<"坐标为("<<xx<<""<<yy<<""<<endl;
 44                 else
 45                 cout<<"Y找到@,耗时" <<vis[xx][yy][z]<<"坐标为("<<xx<<""<<yy<<""<<endl;
 46             }
 47             if(z==1&&mp[xx][yy]=='@')
 48             {
 49                 
 50                 sum=vis[xx][yy][1]+vis[xx][yy][0];
 51                 cout<<"考虑优化,sum=="<<sum<<"=="<<vis[xx][yy][1]<<" + "<<vis[xx][yy][0]<<endl;
 52                 if(mine==0)mine=sum;
 53                 if(mine>sum&&mine)
 54                 {
 55                     cout<<"【实际优化】"<<mine<<"-->>"<<sum<<endl;mine=sum;
 56                 }
 57                 
 58             }
 59             //vis[xx][yy][z]=0;//不需要回溯 
 60             vis[yx][yyy][0]=0;
 61             vis[mx][my][1]=0;
 62             //但是每次都需要保证原坐标是0,不然计数会出问题 ; 
 63         }
 64     }
 65 }
 66 int main()
 67 {
 68     ios_base::sync_with_stdio(false);
 69     cin.tie(0);
 70     cout.tie(0);
 71     while(cin>>n>>m)
 72     {
 73         mine=0;
 74         
 75         char p;
 76         for(int i=0;i<n;i++)
 77         {
 78             for(int k=0;k<m;k++)
 79             {
 80                 cin>>p;
 81                 mp[i][k]=p;
 82                 vis[i][k][0]=0;vis[i][k][1]=0;
 83                 if(p=='Y')yx=i,yyy=k;
 84                 if(p=='M')mx=i,my=k;
 85                 if(p=='#')vis[i][k][0]=1,vis[i][k][1]=1;
 86             }
 87         }
 88         cout<<"    DFS(Y)"<<endl;
 89         dfs(yx,yyy,0);
 90         cout<<"    DFS(M)"<<endl;
 91         dfs(mx,my,1);
 92         cout<<"    结束"<<endl;
 93         cout<<mine*11<<endl; 
 94         for(int i=0;i<n;i++)
 95         {
 96             for(int k=0;k<m;k++)
 97             {
 98                 cout<<vis[i][k][0]<<' ';
 99             }
100             cout<<'\n';
101         }
102         cout<<'\n';
103         for(int i=0;i<n;i++)
104         {
105             for(int k=0;k<m;k++)
106             {
107                 cout<<vis[i][k][1]<<' ';
108             }
109             cout<<'\n';
110         }
111     }
112     return 0;
113 }
DFS调试的代码
复制代码

OVER

posted @   Renhr  阅读(247)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示