Gym - 100971J 两个bfs搞定

题目连接:http://codeforces.com/gym/100971/problem/J

题目大意:给出m,n大的区域,在区域中,1表示机器人1,2表示机器人2,‘.’表示可以通过的区域(但不能同时通过两个),‘#’表示不可以通过的区域,问是否可以将两个机器人互换位置。能输出‘YES’,不能输出‘NO’。

解题思路:判断能通过的条件:1,如果有两条或两条以上不同的路径能从点1到达点2,则可以操作。2,若只有一条路径能从点1到达点2,则判断与点1点2相连的区域内是否存在暂存区域(T形区域,即能将一个点暂时放在T形区域的一个顶点,让另外一个点通过后再出来)。 

题目数据中,m*n<200000,如果用二维数组vis[200000][200000]是绝对不行的,此时只需要200000个点,所以用一维vis[200000]再用一个一维转二维函数就行了。

另外,第一个bfs的作用是寻找点1到点二有几条路径,并检查与点1相连的区域有没有暂存区域,第二个bfs2是检查与点2相连的区域有没有暂存区域。

ac代码:

  1 #include<iostream>
  2 #include<cstring>
  3 #include<queue>
  4 using namespace std;
  5 int vis[200005],visit[200005];
  6 int rr[]={1,-1,0,0},cc[]={0,0,1,-1},m,n,k,k2;
  7 int dd(int a,int b){
  8     if(a>=0&&b>=1&&a<=m-1&&b<=n)
  9     return a*n+b;
 10     return 0;
 11 }
 12 struct fun{
 13     int x,y;
 14 };
 15 fun beg,end;
 16 void bfs()
 17 {
 18     int index;
 19     queue<fun> dui;
 20     dui.push(beg);
 21     vis[dd(beg.x-1,beg.y)]=2;
 22     while(!dui.empty())
 23     {
 24         fun now,next;
 25         now=dui.front();
 26         dui.pop();
 27         index=0;
 28         for(int i=0;i<4;i++)
 29         if(!visit[dd(now.x+rr[i]-1,now.y+cc[i])])//判断暂存区域 
 30             index++;
 31         if(index>=3)
 32             k2=1;
 33         if(now.x==end.x&&now.y==end.y)//判断路径数 
 34         {
 35             k++;
 36             continue;//发现点2,结束扩队。 
 37         }
 38         for(int i=0;i<4;i++)
 39         {
 40             if(!vis[dd(now.x+rr[i]-1,now.y+cc[i])])
 41             {
 42                 next.x=now.x+rr[i];next.y=now.y+cc[i];
 43                 vis[dd(next.x-1,next.y)]=1;
 44                 dui.push(next);
 45             }
 46         }
 47         vis[dd(end.x-1,end.y)]=0;//要恢复点2的可访问性。 
 48     }
 49     return;
 50 }
 51 
 52 void bfs2()
 53 {
 54     int index;
 55     queue<fun> dui;
 56     dui.push(end);
 57     vis[dd(end.x-1,end.y)]=1;
 58     while(!dui.empty())
 59     {
 60         fun now,next;
 61         now=dui.front();
 62         dui.pop();
 63         index=0;
 64         for(int i=0;i<4;i++)
 65         if(!visit[dd(now.x+rr[i]-1,now.y+cc[i])])
 66             index++;
 67         if(index>=3)
 68             k2=1;
 69         for(int i=0;i<4;i++)
 70         {
 71             if(!vis[dd(now.x+rr[i]-1,now.y+cc[i])])
 72             {
 73                 next.x=now.x+rr[i];next.y=now.y+cc[i];
 74                 vis[dd(next.x-1,next.y)]=1;
 75                 dui.push(next);
 76             }
 77         }
 78     }
 79     return;
 80 }
 81 int main()
 82 {
 83     while(cin>>m>>n)
 84     {
 85         char str;
 86         k=k2=0;
 87         memset(vis,1,sizeof(vis));
 88         memset(visit,1,sizeof(visit));
 89         for(int i=1;i<=m;i++)
 90         for(int j=1;j<=n;j++)
 91         {
 92             cin>>str;
 93             if(str=='1')
 94             {
 95                 beg.x=i;
 96                 beg.y=j;
 97                 vis[(i-1)*n+j]=0;
 98             }
 99             else if(str=='2')
100             {
101                 end.x=i;
102                 end.y=j;
103                 vis[(i-1)*n+j]=0;
104             }
105             else if(str=='.')
106             vis[(i-1)*n+j]=0;
107         }
108         for(int i=1;i<=m;i++)
109         for(int j=1;j<=n;j++)
110         visit[(i-1)*n+j]=vis[(i-1)*n+j];
111         bfs();
112         bfs2();
113         if(k>=2||(k==1&&k2))
114         cout<<"YES"<<endl;
115         else
116         cout<<"NO"<<endl;
117     }
118     return 0;
119 }

 

posted @ 2018-07-18 13:43  超人不穿内裤  阅读(160)  评论(0编辑  收藏  举报