B - Labyrinth Gym - 102798B
生活随笔
收集整理的這篇文章主要介紹了
B - Labyrinth Gym - 102798B
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
B - Labyrinth Gym - 102798B
題意:
n * m的地圖,有k個障礙物,給你起點到終點,從起點到終點的最短距離
1<=n,m<=200000
nm<=200000
0<=k<=42
1<=q<=100000
題解:
如果沒有障礙物,兩點之間的最短距離就是曼哈頓距離
如果有障礙物,最短距離就是貼著障礙物走
直接暴力肯定不行 ,我們可以看到k的數量很小,每個障礙物上下左右有四個點,然后求這個四個點分別到其他點的距離,然后答案就是起點到障礙物(上下左右四個方向)的距離+障礙物到終點,取最小值
所有我們要開一個思維數組
dis[d][i][x][y]:第i個障礙物的第d個方向到點(x,y)的距離,我們用vector第三四維是動態開空間,避免超內存
代碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <map> #include <queue>using namespace std;const int INF = 0x3f3f3f3f; int dirx[4] = {0,0,-1,1}; int diry[4] = {1,-1,0,0}; vector<vector<int>>dis[4][44]; int n,m,k,q;struct Point {int x,y; }black[55];map<pair<int,int>,int>mp;int judge(int x,int y) {//判斷點是否超出地圖 if(x <= 0 || y <= 0 || x > n || y > m) return true;return false; }void bfs() {for(int i = 1;i <= k;i++) {int x = black[i].x,y = black[i].y;for(int d = 0;d < 4;d++) {int dx = x + dirx[d];int dy = y + diry[d];dis[d][i].resize(n + 1);//第三維開n+1的空間for(int ci = 1;ci <= n;ci++) {//初始化所有距離dis[d][i][ci].resize(m + 1);for(int cj = 1;cj <= m;cj++) {dis[d][i][ci][cj] = INF;}}if(judge(dx,dy)) continue;if(mp.count({dx,dy})) continue;dis[d][i][dx][dy] = 0;queue<pair<int,int>>Q;Q.push({dx,dy});while(!Q.empty()) {//開始跑bfs pair<int,int> now = Q.front();Q.pop();int x = now.first,y = now.second;for(int cd = 0;cd < 4;cd++) {int dx = x + dirx[cd];int dy = y + diry[cd];if(judge(dx,dy)) continue;if(dis[d][i][dx][dy] != INF) continue;if(mp.count({dx,dy})) continue;dis[d][i][dx][dy] = dis[d][i][x][y] + 1;Q.push({dx,dy});}}}} }bool check(int x1,int y1,int x2,int y2) { //這個區域內是否有黑洞if(x1 > x2) swap(x1,x2);if(y1 > y2) swap(y1,y2);for(int i = 1;i <= k;i++) {if(black[i].x <= x2 && black[i].x >= x1 && black[i].y <= y2 && black[i].y >= y1) return true;}return false; }int main() {scanf("%d%d%d%d",&n,&m,&k,&q);for(int i = 1;i <= k;i++) {scanf("%d%d",&black[i].x,&black[i].y);mp[{black[i].x,black[i].y}] = 1;}bfs();for(int i = 1;i <= q;i++) {int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);if(check(x1,y1,x2,y2)) {int ans = 0x3f3f3f3f;for(int j = 1;j <= k;j++) {for(int d = 0;d < 4;d++) {int dx = black[j].x + dirx[d];int dy = black[j].y + diry[d];if(judge(dx,dy)) continue;ans = min(ans,dis[d][j][x1][y1] + dis[d][j][x2][y2]);}}if(ans == INF) printf("-1\n");else printf("%d\n",ans);} else {//如果沒有黑洞,直接曼哈頓距離 printf("%d\n",abs(x1 - x2) + abs(y1 - y2));}}return 0; }總結
以上是生活随笔為你收集整理的B - Labyrinth Gym - 102798B的全部內容,希望文章能夠幫你解決所遇到的問題。