[HIHO1328]逃离迷宫(bfs,位压)

题目链接:http://hihocoder.com/problemset/problem/1328

这个题bfs到时候不止要存当前的坐标,还要存当前有哪几把钥匙。因为5把钥匙,所以可以直接用位来存,这样也可以解决一个房间里有好几把钥匙的情况。

还有就是走的过程中,一个点重复走多少次的问题,我们用vis(x,y,k)来记录坐标(x,y)的时候拿着钥匙位压后为k的情况,并且初始化成0x7f7f7f,每次更新最短路,假如有重复走并且拥有钥匙情况相同的情况就可以剪掉了。

  1 /*
  2 ━━━━━┒ギリギリ♂ eye!
  3 ┓┏┓┏┓┃キリキリ♂ mind!
  4 ┛┗┛┗┛┃\○/
  5 ┓┏┓┏┓┃ /
  6 ┛┗┛┗┛┃ノ)
  7 ┓┏┓┏┓┃
  8 ┛┗┛┗┛┃
  9 ┓┏┓┏┓┃
 10 ┛┗┛┗┛┃
 11 ┓┏┓┏┓┃
 12 ┛┗┛┗┛┃
 13 ┓┏┓┏┓┃
 14 ┃┃┃┃┃┃
 15 ┻┻┻┻┻┻
 16 */
 17 #include <algorithm>
 18 #include <iostream>
 19 #include <iomanip>
 20 #include <cstring>
 21 #include <climits>
 22 #include <complex>
 23 #include <cassert>
 24 #include <cstdio>
 25 #include <bitset>
 26 #include <vector>
 27 #include <deque>
 28 #include <queue>
 29 #include <stack>
 30 #include <ctime>
 31 #include <set>
 32 #include <map>
 33 #include <cmath>
 34 using namespace std;
 35 #define fr first
 36 #define sc second
 37 #define cl clear
 38 #define BUG puts("here!!!")
 39 #define W(a) while(a--)
 40 #define pb(a) push_back(a)
 41 #define Rint(a) scanf("%d", &a)
 42 #define Rll(a) scanf("%I64d", &a)
 43 #define Rs(a) scanf("%s", a)
 44 #define Cin(a) cin >> a
 45 #define FRead() freopen("in", "r", stdin)
 46 #define FWrite() freopen("out", "w", stdout)
 47 #define Rep(i, len) for(int i = 0; i < (len); i++)
 48 #define For(i, a, len) for(int i = (a); i < (len); i++)
 49 #define Cls(a) memset((a), 0, sizeof(a))
 50 #define Clr(a, x) memset((a), (x), sizeof(a))
 51 #define Full(a) memset((a), 0x7f7f, sizeof(a))
 52 #define lrt rt << 1
 53 #define rrt rt << 1 | 1
 54 #define pi 3.14159265359
 55 #define RT return
 56 #define lowbit(x) x & (-x)
 57 #define onenum(x) __builtin_popcount(x)
 58 typedef long long LL;
 59 typedef long double LD;
 60 typedef unsigned long long ULL;
 61 typedef pair<int, int> pii;
 62 typedef pair<string, int> psi;
 63 typedef pair<LL, LL> pll;
 64 typedef map<string, int> msi;
 65 typedef vector<int> vi;
 66 typedef vector<LL> vl;
 67 typedef vector<vl> vvl;
 68 typedef vector<bool> vb;
 69 
 70 typedef struct Node {
 71     int x, y;
 72     int s;
 73     int k;
 74     Node() {}
 75     Node(int xx, int yy, int ss, int kk) : x(xx), y(yy), s(ss), k(kk) {}
 76 }Node;
 77 const int dx[5] = {1,-1,0,0};
 78 const int dy[5] = {0,0,1,-1};
 79 const int maxn = 110;
 80 int n, m, k;
 81 int sx, sy, ex, ey;
 82 int vis[maxn][maxn][33];
 83 char G[maxn][maxn];
 84 char ks[maxn][maxn];
 85 int ret;
 86 queue<Node> q;
 87 
 88 bool ok(int x, int y) {
 89     return x >= 0 && y >= 0 && x < n && y < m && G[x][y] != '#';
 90 }
 91 
 92 bool yes(int x, int y, int k) {
 93     if(G[x][y] == '.') return 1;
 94     return k & (1 << (G[x][y] - 'A'));
 95 }
 96 
 97 void bfs() {
 98     while(!q.empty()) q.pop();
 99     q.push(Node(sx, sy, 0, 0));
100     vis[sx][sy][0] = 0;
101     while(!q.empty()) {
102         Node t = q.front(); q.pop();
103         // printf("%d
", t.k);
104         if(t.x == ex && t.y == ey) {
105             ret = min(ret, t.s);
106             return;
107         }
108         Rep(i, 4) {
109             int x = t.x + dx[i];
110             int y = t.y + dy[i];
111             if(ok(x, y)) {
112                 int ck =  t.k | ks[x][y];
113                 if(vis[x][y][ck] > t.s + 1 && yes(x, y, ck)) {
114                     vis[x][y][ck] = t.s + 1;
115                     q.push(Node(x, y, t.s+1, ck));
116                 }
117             }
118         }
119     }
120 }
121 
122 int main() {
123     // FRead();
124     int x, y;
125     while(~scanf("%d%d%d%d%d%d%d",&n,&m,&k,&sx,&sy,&ex,&ey)) {
126         Clr(vis, 0x7f7f); Cls(G); Cls(ks); ret = 0x7f7f;
127         Rep(i, n) Rs(G[i]);
128         Rep(i, k) {
129             Rint(x); Rint(y);
130             ks[x][y] |= (1 << i);
131         }
132         bfs();
133         if(ret != 0x7f7f) printf("%d
", ret);
134         else printf("-1
");
135     }
136     RT 0;
137 }

这种判断重复的方法是不对的,因为会在一个出不去而不停兜圈子,拿不到钥匙并且会超时。

  1 /*
  2 ━━━━━┒ギリギリ♂ eye!
  3 ┓┏┓┏┓┃キリキリ♂ mind!
  4 ┛┗┛┗┛┃\○/
  5 ┓┏┓┏┓┃ /
  6 ┛┗┛┗┛┃ノ)
  7 ┓┏┓┏┓┃
  8 ┛┗┛┗┛┃
  9 ┓┏┓┏┓┃
 10 ┛┗┛┗┛┃
 11 ┓┏┓┏┓┃
 12 ┛┗┛┗┛┃
 13 ┓┏┓┏┓┃
 14 ┃┃┃┃┃┃
 15 ┻┻┻┻┻┻
 16 */
 17 #include <algorithm>
 18 #include <iostream>
 19 #include <iomanip>
 20 #include <cstring>
 21 #include <climits>
 22 #include <complex>
 23 #include <cassert>
 24 #include <cstdio>
 25 #include <bitset>
 26 #include <vector>
 27 #include <deque>
 28 #include <queue>
 29 #include <stack>
 30 #include <ctime>
 31 #include <set>
 32 #include <map>
 33 #include <cmath>
 34 using namespace std;
 35 #define fr first
 36 #define sc second
 37 #define cl clear
 38 #define BUG puts("here!!!")
 39 #define W(a) while(a--)
 40 #define pb(a) push_back(a)
 41 #define Rint(a) scanf("%d", &a)
 42 #define Rll(a) scanf("%I64d", &a)
 43 #define Rs(a) scanf("%s", a)
 44 #define Cin(a) cin >> a
 45 #define FRead() freopen("in", "r", stdin)
 46 #define FWrite() freopen("out", "w", stdout)
 47 #define Rep(i, len) for(int i = 0; i < (len); i++)
 48 #define For(i, a, len) for(int i = (a); i < (len); i++)
 49 #define Cls(a) memset((a), 0, sizeof(a))
 50 #define Clr(a, x) memset((a), (x), sizeof(a))
 51 #define Full(a) memset((a), 0x7f7f7f, sizeof(a))
 52 #define lrt rt << 1
 53 #define rrt rt << 1 | 1
 54 #define pi 3.14159265359
 55 #define RT return
 56 #define lowbit(x) x & (-x)
 57 #define onenum(x) __builtin_popcount(x)
 58 typedef long long LL;
 59 typedef long double LD;
 60 typedef unsigned long long ULL;
 61 typedef pair<int, int> pii;
 62 typedef pair<string, int> psi;
 63 typedef pair<LL, LL> pll;
 64 typedef map<string, int> msi;
 65 typedef vector<int> vi;
 66 typedef vector<LL> vl;
 67 typedef vector<vl> vvl;
 68 typedef vector<bool> vb;
 69 
 70 typedef struct Node {
 71     int x, y;
 72     int s;
 73     int k;
 74     Node() {}
 75     Node(int xx, int yy, int ss) : x(xx), y(yy), s(ss) { k = 0; }
 76     Node(int xx, int yy, int ss, int kk) : x(xx), y(yy), s(ss), k(kk) {}
 77 }Node;
 78 const int dx[5] = {1,-1,0,0};
 79 const int dy[5] = {0,0,1,-1};
 80 const int maxn = 110;
 81 int n, m, k;
 82 int sx, sy, ex, ey;
 83 char G[maxn][maxn];
 84 char ks[maxn][maxn];
 85 int ret;
 86 queue<Node> q;
 87 
 88 bool ok(int x, int y) {
 89     return x >= 0 && y >= 0 && x < n && y < m && G[x][y] != '#';
 90 }
 91 
 92 void bfs() {
 93     while(!q.empty()) q.pop();
 94     q.push(Node(sx, sy, 0, 0));
 95     int wtf = 0;
 96     while(!q.empty()) {
 97         if(wtf++ == 9000000) return;
 98         Node t = q.front(); q.pop();
 99         // printf("%d
", t.k);
100         if(t.x == ex && t.y == ey) {
101             ret = min(ret, t.s);
102             return;
103         }
104         Rep(i, 4) {
105             int x = t.x + dx[i];
106             int y = t.y + dy[i];
107             if(ok(x, y)) {
108                 int cur =  t.k | ks[x][y];
109                 if(G[x][y] == '.' ||  (cur & (1 << (G[x][y] - 'A')))) {
110                     q.push(Node(x, y, t.s+1, cur));
111                 }
112             }
113         }
114     }
115 }
116 
117 int main() {
118     // FRead();
119     int x, y;
120     while(~scanf("%d%d%d%d%d%d%d",&n,&m,&k,&sx,&sy,&ex,&ey)) {
121         Cls(G); Cls(ks); ret = 0x7f7f7f;
122         Rep(i, n) Rs(G[i]);
123         Rep(i, k) {
124             Rint(x); Rint(y);
125             ks[x][y] |= (1 << i);
126         }
127         bfs();
128         if(ret == 0x7f7f7f) printf("-1
");
129         else printf("%d
", ret);
130     }
131     RT 0;
132 }
View Code
原文地址:https://www.cnblogs.com/kirai/p/5618849.html