Gym - 100971J- Robots at Warehouse-bfs&&dfs

http://codeforces.com/gym/100971/problem/J
搜索姿势有待提高。。
给定两个机器人1 和2的位置,问你可否让这俩货换位置,已知俩货不能同时在一个地方。。
我的思路:dfs两次路径。如果都相同,说明只有一条路,否则说明有两条,然后再一条路的情况下判断t型路。。
dfs找路完全是随机的。。可能把所有的都遍历了也可能到达了其他就结束了。。这个想法完全想当然。。

看的题解:bfs,判断是否连通。如果有的话,判断情况,
如果存在一个t型点,那么一定可以。
否则判断终点数。
一条路径下不可以(并且没有t型点)的时候端点为2
有多条时为0.。
还有别人写的 dfs代码,值得好好学习。。

直接用char数组,说数组开的太大了。。。只好用string数组阴奉阳违之。。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
/*1 先广搜一下,如果搜不到肯定不是。
然后分为三种情况 1  出现t字型插口,肯定可以
2 出现一个线的情况,
*/
const int maxn=200001;
vector<bool>vis[maxn];
int fx[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
string a[maxn];
int m,n;
int bfs(int a1,int b1)
{      //memset(vis,false,sizeof(vis));
      for(int i=1;i<=m;i++)
      {  for(int j=0;j<n;j++)
          vis[i].push_back(0);


      }

      vis[a1][b1]=true;
      queue<pair<int,int> >q;
      q.push(make_pair(a1,b1));
      while(!q.empty())
      {    pair<int ,int >u=q.front();
            q.pop();
            for(int i=0;i<4;i++)
            {   int x2=u.first+fx[i][0];
                int y2=u.second+fx[i][1];
                 if(x2>=1&&x2<=m&&y2>=0&&y2<n&&a[x2][y2]!='#'&&!vis[x2][y2])
                     {q.push(make_pair(x2,y2));
                      vis[x2][y2]=true;
                     }
            }
      }
return 0;
}
int main()
{  int ux,uy,vx,vy;
   char cc;
     cin>>m>>n;
     //a[0].push_back("1");
     a[0]='1';
          for(int i=1;i<=m;i++)
        {  //a[i].push_back("1");
            //for(int j=0;j<=n;j++)
           cin>>a[i];
             //a[i].push_back(cc);
             //cin>>a[i][j];
           for(int j=0;j<n;j++)
           if(a[i][j]=='1')
           {ux=i;uy=j;}
           else if(a[i][j]=='2')
             {vx=i;vy=j;}

        }
       bfs(ux,uy);
       /*for(int i=1;i<=m;i++)
       {{for(int j=1;j<=n;j++)
          if(vis[i][j])
            cout<<"1 ";
          else
            cout<<"0 ";

       }
        cout<<endl;
       }*/
       //cout<<"1"<<endl;
       if(!vis[vx][vy])
       {  puts("NO");return 0;
       }

       else
       {   int tt=0;
           bool flag=false;
            for(int i=1;i<=m&&!flag;i++)
             for(int j=0;j<n&&!flag;j++)
             {   if(vis[i][j])
                 {   int ans=0;
                     for(int x=0;x<4;x++)
                     {   int x1=fx[x][0]+i;
                         int y1=fx[x][1]+j;
                          if(a[x1][y1]!='#'&&x1>=1&&x1<=m&&y1>=0&&y1<n)
                             ans++;

                     }
                     if(ans>2) flag=true;
                           else if(ans==1) tt++;
                 }
             }
            if(flag)
                puts("YES");
            else {if(tt==2)
              puts("NO");
              else if(tt==0)
                puts("YES");
              }




       }






    return 0;
}
#include<cstdio>
#define N 200005
int n,m,ux,uy,ax,ay,a[N],u[N],ck,ans,fx[4]= {1,-1,0,0},fy[4]= {0,0,1,-1};
char c;
void dfs(int x,int y,int s){
    if(x==ux&&y==uy&&s>2||x==ax&&y==ay)//走回起点(s是第几步)或走到终点
        ans++;
    if(u[x*m-m+y]||ans>2||ans&&ck)return;
    u[x*m-m+y]=1;
    int r=0;
    for(int i=0;i<4;i++){
        int nx=x+fx[i];
        int ny=y+fy[i];
        if(nx&&nx<=n&&ny&&ny<=m&&a[nx*m-m+ny]){
            r++;//点的度
            if(r>2)ck=1;
            dfs(nx,ny,s+1);
        }
    }
}
int main(){
    scanf("%d%d ",&n,&m);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            c=getchar();
            if(c!='#')
                a[i*m-m+j]=1;
            if(c=='1')
            {
                ux=i;
                uy=j;
            }
            else if(c=='2')
            {
                ax=i;
                ay=j;
            }
        }
        getchar();
    }
    dfs(ux,uy,0);
    if(ans>2||ans&&ck)printf("YES");
    else printf("NO");
    return 0;
}
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值