题目大意: 给你一个n × m 的图,有p种宝箱, 每个点上有一个种类为a[ i ][ j ]的宝箱,a[ i ][ j ] 的宝箱里有 a[ i ][ j ] + 1的钥匙,第一种宝箱是没有锁的,
第p类宝箱只有一个且里面由宝藏,你现在在(1 ,1)问你最少需要多少步才能拿到宝藏。 (n, m <= 300)
思路:这题真的好恶心啊。。。 我们考虑p类宝箱只能从p - 1类转移过来, 这样我们就能从第一类宝箱开始往后递推, 但是最坏的情况, p 类 和p - 1类,都有45000
个点, 那么复杂度就会很大。。。 所以我们要分类讨论, 对于 (p.size()) * (p + 1. size()) > n * m 的点我们在图上进行暴力转移,复杂度微n × m, 否则我们直接暴力
转移。。。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define fi first 4 #define se second 5 #define mk make_pair 6 #define pii pair<int,int> 7 #define piii pair<int, pair<int,int>> 8 using namespace std; 9 10 const int N=300+1; 11 const int M=1e4+7; 12 const int inf=0x3f3f3f3f; 13 const LL INF=0x3f3f3f3f3f3f3f3f; 14 const int mod=1e9 + 7; 15 16 vector<pair<int, pii>> vec[N * N]; 17 int n, m, p, idx, a[N][N], S, T, f[N * N], hs[N][N], vis[N][N]; 18 bool flag[N][N]; 19 int dx[] = {1, -1, 0, 0}, dy[] = {0 ,0 , 1, -1}; 20 21 int dis(pii &a, pii &b) { 22 return abs(a.fi - b.fi) + abs(a.se - b.se); 23 } 24 25 bool check(int x, int y) { 26 if(x < 1 || x > n) return false; 27 if(y < 1 || y > m) return false; 28 return true; 29 } 30 31 void bfs(int p) { 32 for(int i = 1; i <= n; i++) { 33 for(int j = 1; j <= m; j++) { 34 flag[i][j] = false; 35 vis[i][j] = inf; 36 } 37 } 38 queue<piii> Q; 39 for(auto u : vec[p]) { 40 Q.push(mk(f[u.fi], u.se)); 41 vis[u.se.fi][u.se.se] = f[u.fi]; 42 } 43 44 while(!Q.empty()) { 45 piii u = Q.front(); Q.pop(); 46 for(int i = 0; i < 4; i++) { 47 piii nx = mk(vis[u.se.fi][u.se.se] + 1, mk(u.se.fi + dx[i], u.se.se + dy[i])); 48 if(check(nx.se.fi, nx.se.se)) { 49 if(vis[nx.se.fi][nx.se.se] > nx.fi) 50 { 51 vis[nx.se.fi][nx.se.se] = nx.fi; 52 if(!flag[nx.se.fi][nx.se.se]) { 53 flag[nx.se.fi][nx.se.se] = true; 54 Q.push(nx); 55 } 56 } 57 } 58 } 59 flag[u.se.fi][u.se.se] = false; 60 } 61 62 for(auto u : vec[p + 1]) { 63 f[u.fi] = vis[u.se.fi][u.se.se]; 64 } 65 } 66 67 int main() { 68 memset(f, inf, sizeof(f)); 69 70 scanf("%d%d%d", &n, &m, &p); 71 for(int i = 1; i <= n; i++) 72 for(int j = 1; j <= m; j++) 73 scanf("%d", &a[i][j]); 74 75 for(int i = 1; i <= n; i++) { 76 for(int j = 1; j <= m; j++) { 77 vec[a[i][j]].push_back(mk(++idx, mk(i, j))); 78 hs[i][j] = idx; 79 if(a[i][j] == p) { 80 S = 0; 81 T = idx; 82 } 83 } 84 } 85 f[0] = 0; 86 vec[0].push_back(mk(0, mk(1, 1))); 87 for(int i = 1; i <= p; i++) { 88 if(vec[i - 1].size() * vec[i].size() <= n * m) { 89 for(auto u : vec[i - 1]) { 90 for(auto v : vec[i]) { 91 f[v.fi] = min(f[v.fi], f[u.fi] + dis(u.se, v.se)); 92 } 93 } 94 } else { 95 bfs(i - 1); 96 } 97 } 98 printf("%d ", f[T]); 99 return 0; 100 } 101 /* 102 */