题目连接: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 }