http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1566
题意还是蛮难懂的,至少对于我来说,需要认真读题。
输入矩阵的每一个数字换成2进制后,顺时针围一圈,用1表示墙,0表示空,这样就可以表示出一个迷宫,现在就是判断这个迷宫属于4种类型中哪种类型。
参考了 大神博客。构图很难,并且想法跟以往的题都不一样。是一个好题。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <string> 9 #include <set> 10 #include <functional> 11 #include <numeric> 12 #include <sstream> 13 #include <stack> 14 #include <map> 15 #include <queue> 16 #pragma comment(linker, "/STACK:102400000,102400000") 17 #define CL(arr, val) memset(arr, val, sizeof(arr)) 18 19 #define ll long long 20 #define inf 0x7f7f7f7f 21 #define lc l,m,rt<<1 22 #define rc m + 1,r,rt<<1|1 23 #define pi acos(-1.0) 24 25 #define L(x) (x) << 1 26 #define R(x) (x) << 1 | 1 27 #define MID(l, r) (l + r) >> 1 28 #define Min(x, y) (x) < (y) ? (x) : (y) 29 #define Max(x, y) (x) < (y) ? (y) : (x) 30 #define E(x) (1 << (x)) 31 #define iabs(x) (x) < 0 ? -(x) : (x) 32 #define OUT(x) printf("%I64d\n", x) 33 #define lowbit(x) (x)&(-x) 34 #define Read() freopen("a.txt", "r", stdin) 35 #define Write() freopen("b.txt", "w", stdout); 36 #define maxn 1000000000 37 #define N 2510 38 #define mod 1000000000 39 using namespace std; 40 41 int n,m; 42 int num[55][55],vis[55][55]; 43 int dir[4][3]={1,0,2,-1,0,8,0,1,4,0,-1,1}; 44 //这里必须要对应 是为了防止往回走 45 struct point 46 { 47 int a,b; 48 }; 49 int main() 50 { 51 //freopen("a.txt","r",stdin); 52 char s[55]; 53 int x,y,nx,ny; 54 while(~scanf("%d%d",&n,&m)) 55 { 56 if(!n&&!m) break; 57 for(int i=1;i<=n;i++) 58 { 59 scanf("%s",s+1); 60 for(int j=1;j<=m;j++) 61 { 62 if(s[j]>=‘0‘&&s[j]<=‘9‘) num[i][j]=s[j]-‘0‘; 63 else num[i][j]=s[j]-‘A‘+10; 64 num[i][j]=~num[i][j]; //读入之后 按位取反 ,能走的变成1 不能走的变成0 65 } 66 } 67 x=0; //找出 起点和终点 68 for(int i=1;i<=n;i++) //第一列或者第m列 看左右边界 69 { 70 if(num[i][1]&1) //代表表示 num[i][1]的四位2进制数中最后一位是1 代表有缺口 71 { 72 if(!x) x=i,y=1; 73 else nx=i,ny=1; 74 } 75 if(num[i][m]&4) 76 { 77 if(!x) x=i,y=m; 78 else nx=i,ny=m; 79 } 80 } 81 for(int i=1;i<=m;i++) //同上,看上下边界 82 { 83 if(num[1][i]&8) 84 { 85 if(!x) x=1,y=i; 86 else nx=1,ny=i; 87 } 88 if(num[n][i]&2) 89 { 90 if(!x) x=n,y=i; 91 else nx=n,ny=i; 92 } 93 } 94 // printf("%d %d %d %d\n",x,y,nx,ny); 95 memset(vis,0,sizeof(vis)); 96 int mul=0; 97 queue<point>que; 98 point now,next; 99 now.a=x,now.b=y; 100 vis[now.a][now.b]=16; 101 que.push(now); 102 while(!que.empty()) //扩展所有能到达的点 103 { 104 next=que.front();que.pop(); 105 for(int i=0;i<4;i++) 106 { 107 if(vis[next.a][next.b]==dir[i][2]) continue; //已经访问过,防止往回走, 108 if(num[next.a][next.b]&dir[i][2]) //该方向能访问 109 { 110 now.a=next.a+dir[i][0]; 111 now.b=next.b+dir[i][1]; 112 if(now.a>=1&&now.a<=n&&now.b>=1&&now.b<=m) 113 { 114 if(vis[now.a][now.b]) mul=1; //多次到达同一个点 115 else 116 { 117 if(dir[i][2]==4) vis[now.a][now.b]=1; //赋值相反方向的值给vis,防止往回走,跟上面的判断对应 118 else if(dir[i][2]==1) vis[now.a][now.b]=4; 119 else if(dir[i][2]==8) vis[now.a][now.b]=2; 120 else if(dir[i][2]==2) vis[now.a][now.b]=8; 121 que.push(now); 122 } 123 } 124 } 125 } 126 } 127 if(vis[nx][ny]) //能到出口 128 { 129 bool flag=0; 130 for(int i=1;i<=n;i++) 131 { 132 for(int j=1;j<=m;j++) 133 if(!vis[i][j]) 134 { 135 //printf("%d %d\n",i,j); 136 flag=1; 137 break; 138 } 139 if(flag) break; 140 } 141 if(flag) printf("UNREACHABLE CELL\n"); //有点不能到达 142 else 143 { 144 if(mul) printf("MULTIPLE PATHS\n"); //多次到达 145 else printf("MAZE OK\n"); //只有一条路径 146 } 147 } 148 else printf("NO SOLUTION\n"); //没有路径 149 } 150 return 0; 151 }
时间: 2024-10-23 17:28:46