Prison Escape
这是codechef starter 134 div4
的第六题。
题目链接
题目大意
NxM的01矩阵,0代表罪犯,1代表守卫者。罪犯可以上下左右移动,计算罪犯最少需要经过几个守卫者才能逃出这个矩阵。我们要求出这些罪犯里边经过最少守卫者数量的最大值。
数据范围:T 1000,N和M 3e5,NxM<3e5
。
赛时回顾
一眼最短路,但是看见数据范围就没有去写代码。我觉得每个0点去执行最短路算法应该会超时。或者直接每个0进行bfs应该也会超时。
正解
有个东西叫多源最短路。实际上我应该换位思考,不是去求0到边界的最短路,而是边界到0的最短路。多源最短路有两种方法,一是设置虚拟节点连接到所有源,二是直接把所有源节点压入队列中,不需要理会。
所以实际上这个题目是典型的0-1BFS
问题。我们只需要将所有边界节点压入队列中,然后一点点向内更新距离即可。最后答案就是d[i][j]
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mxlen = 3e5+10;
int main() { int T; cin >> T; while(T--){ int n,m; cin >> n >> m; string a[n]; for(int i=0;i<n;i++){ cin >> a[i]; } vector<vector<int> > d(n,vector<int>(m,INT_MAX)); deque<pair<int,int> > dq; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(i==0||j==0||i==n-1||j==m-1){ d[i][j]=a[i][j]-'0'; if(d[i][j]==0){ dq.push_front({i,j}); } else dq.push_back({i,j}); } } } int dx[] = {0,0,1,-1}; int dy[] = {1,-1,0,0}; while(!dq.empty()){ int x = dq.front().first; int y = dq.front().second; dq.pop_front(); for(int i=0;i<4;i++){ int xx = x+dx[i]; int yy = y+dy[i]; if(xx<0||yy<0||xx>=n||yy>=m) continue;
int weight = a[xx][yy]-'0'; if(d[x][y]+weight<d[xx][yy]){ d[xx][yy]=d[x][y]+weight; if(weight==0){ dq.push_front({xx,yy}); } else dq.push_back({xx,yy}); } } }
int ans = 0; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(a[i][j]=='0'){ ans = max(ans,d[i][j]); } } } cout<<ans<<endl; } return 0; }
|