胜利大逃亡(续)
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6070 Accepted Submission(s): 2096
Problem Description
Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……
这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。
这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。
Input
每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:
. 代表路 * 代表墙 @ 代表Ignatius的起始位置 ^ 代表地牢的出口 A-J 代表带锁的门,对应的钥匙分别为a-j a-j 代表钥匙,对应的门分别为A-J
每组测试数据之间有一个空行。
. 代表路 * 代表墙 @ 代表Ignatius的起始位置 ^ 代表地牢的出口 A-J 代表带锁的门,对应的钥匙分别为a-j a-j 代表钥匙,对应的门分别为A-J
每组测试数据之间有一个空行。
Output
针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。
Sample Input
4 5 17
@A.B.
a*.*.
*..*^
c..b*
4 5 16
@A.B.
a*.*.
*..*^
c..b*
Sample Output
16
-1
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 #include<math.h> 5 typedef long long ll ; 6 const int M = 20 + 4 , mod = 1700003 , bas = 29 ; 7 char map[M][M] ; 8 int a[M][M][2500 + 10] ; 9 int move[][2] = {{1,0} , {-1,0} , {0,1} , {0,-1}} ; 10 int n , m , t ; 11 struct node 12 { 13 int x , y , step ; 14 int key ; 15 }; 16 17 int bfs (int sx , int sy , int ex , int ey) 18 { 19 // puts ("heheda") ; 20 std::queue<node> q ; 21 while (!q.empty ()) q.pop () ; 22 node ans , tmp ; 23 q.push ((node) {sx , sy , 0,0}) ; 24 a[sx][sy][0] = 1 ; 25 while (!q.empty ()) { 26 ans = q.front () ; q.pop () ; 27 // puts ("He") ; 28 // printf ("s----------(%d,%d),%d " , (ans.x , ans.y) , ans.step) ; 29 if (ans.step >= t) return -1 ; 30 if (ans.x == ex &&ans.y == ey ) return a[ans.x][ans.y][ans.key]; 31 for (int i = 0 ; i < 4 ; i ++) { 32 tmp.x = ans.x + move[i][0] ; tmp.y = ans.y + move[i][1] ; 33 if (tmp.x < 0 || tmp.y < 0 || tmp.x >= n || tmp.y >= m) continue ; 34 if (map[tmp.x][tmp.y] == '*') continue ; 35 char door = map[tmp.x][tmp.y] ; 36 if (door >= 'A' && door <= 'J' ) if ( ! (ans.key & (int)pow(2,door - 'A') ) ) continue ; 37 tmp.step = ans.step + 1 ; 38 tmp.key = ans.key ; 39 if (door >= 'a' && door <= 'j' ) tmp.key = tmp.key | ((int) pow (2 , door - 'a')) ; 40 if (a[tmp.x][tmp.y][tmp.key] != - 1 ) continue ; 41 a[tmp.x][tmp.y][tmp.key] = tmp.step ; 42 q.push (tmp) ; 43 } 44 } 45 return -1 ; 46 } 47 48 int main () 49 { 50 //freopen ("a.txt" , "r" , stdin ); 51 while (scanf ("%d%d%d" , &n , &m , &t) == 3) { 52 int x , y , ex , ey ; 53 // printf ("n=%d,m=%d,t=%d " , n , m , t ) ; 54 memset (a , - 1 , sizeof(a)) ; 55 for (int i = 0 ; i < n ; i ++) scanf ("%s" , map[i]) ; 56 for (int i = 0 ; i < n ; i ++) { 57 for (int j = 0 ; j < m ; j ++) { 58 if (map[i][j] == '@') {x = i , y = j ;} 59 else if (map[i][j] == '^') {ex = i , ey = j ;} ; 60 } 61 } 62 printf ("%d " , bfs (x , y , ex , ey) ) ; 63 } 64 return 0 ; 65 } 66 /* 67 #include<stdio.h> 68 #include<string.h> 69 #include<queue> 70 typedef long long ll ; 71 const int M = 20 + 4 , mod = 1700003 , bas = 29 ; 72 char map[M][M] ; 73 int move[][2] = {{1,0} , {-1,0} , {0,1} , {0,-1}} ; 74 int n , m , t ; 75 struct node 76 { 77 int x , y , step ; 78 bool key[30] ; 79 }; 80 struct hash 81 { 82 int w , nxt ; 83 int x , y , key ; 84 }e[mod]; 85 int E = 0 , H[mod]; 86 87 void insert (int x) 88 { 89 int y = x % mod ; 90 if (y < 0) y += mod ; 91 e[++ E].w = x ; 92 e[E].nxt = H[y] ; 93 H[y] = E ; 94 } 95 96 bool find (int x , node tmp ) 97 { 98 int y = x % mod ; 99 if (y < 0) y += mod ; 100 for (int i = H[y] ; i ; i = e[i].nxt) { 101 if (e[i].w == x) { 102 if (e[i].x == tmp.x && e[i].y == tmp.y && e[i].key) 103 } 104 } 105 return false ; 106 } 107 108 int bfs (int sx , int sy , int ex , int ey) 109 { 110 std::queue<node> q ; 111 while (!q.empty ()) q.pop () ; 112 node ans , tmp ; 113 q.push ((node) {sx , sy , 0}) ; 114 while (!q.empty ()) { 115 ans = q.front () ; q.pop () ; 116 if (ans.step >= t) return -1 ; 117 if (ans.x == ex && ans.y == ey ) return ans.step ; 118 for (int i = 0 ; i < 4 ; i ++) { 119 tmp.x = ans.x + move[i][0] ; tmp.y = ans.y + move[i][1] ; 120 if (tmp.x < 0 || tmp.y < 0 || tmp.x >= n || tmp.y >= m) continue ; 121 if (map[tmp.x][tmp.y] == '*') continue ; 122 char door = map[tmp.x][tmp.y] ; 123 if (door >= 'A' && door <= 'J' && ans.key[door - 'A' ] == 0) continue ; 124 for (int j = 0 ; j < 26 ; j ++) { 125 tmp.key[j] = ans.key[j] ; 126 } 127 tmp.step = ans.step + 1 ; 128 if (door >= 'a' && door <= 'j') tmp.key[door - 'a' ] = 1 ; 129 ll rhs = 1 , fac = 1; 130 rhs = (1ll*rhs*fac + tmp.x) % mod ; fac *= 1ll*bas ; rhs = (1ll*rhs*fac+tmp.y) % mod ; fac *= 1ll*bas ; 131 for (int i = 0 ; i < 26 ; i ++) { 132 if (tmp.key[i]) { 133 rhs = (1ll*rhs*fac + i * i *i + i *i) % mod ; 134 fac *= 1ll * bas ; 135 } 136 } 137 if (find (rhs , tmp)) continue ; 138 insert (rhs , tmp) ; 139 q.push (tmp) ; 140 } 141 } 142 return -1 ; 143 } 144 145 int main () 146 { 147 // freopen ("a.txt" , "r" , stdin ); 148 while (~ scanf ("%d%d%d" , &n , &m , &t) ) { 149 int x , y , ex , ey ; 150 for (int i = 0 ; i < n ; i ++) scanf ("%s" , map[i]) ; 151 for (int i = 0 ; i < n ; i ++) { 152 for (int j = 0 ; j < m ; j ++) { 153 if (map[i][j] == '@') {x = i , y = j ;} 154 else if (map[i][j] == '^') {ex = i , ey = j ;} ; 155 } 156 } 157 E = 0 ; 158 memset (H, 0 , sizeof(H)) ; 159 printf ("%d " , bfs (x , y , ex , ey) ) ; 160 } 161 return 0 ; 162 } 163 */
一开始把x , y , key,当做hash的元素,得到一个hash值。
一直wa,后来杰神说,要更加精确的hash值,就是多加点辅助值。
so明白了,不过果然变得很麻烦,给过还是。。。。。
附上用二进制保存钥匙状态的程序。