《幻塔》甜蜜工坊送禮攻略 最高分情人節禮物搭配
題目描述
題目背景
巫妖王的天災軍團終於捲土重來,血色十字軍組織了一支先鋒軍前往諾森德大陸對抗天災軍團,以及一切沾有亡靈氣息的生物。孤立於聯盟和部落的血色先鋒軍很快就遭到了天災軍團的重重包圍,現在他們將主力只好聚集了起來,以抵抗天災軍團的圍剿。可怕的是,他們之中有人感染上了亡靈瘟疫,如果不設法阻止瘟疫的擴散,很快就會遭到滅頂之災。大領主阿比迪斯已經開始調查瘟疫的源頭。原來是血色先鋒軍的內部出現了叛徒,這個叛徒已經投靠了天災軍團,想要將整個血色先鋒軍全部轉化為天災軍團!無需驚訝,你就是那個叛徒。在你的行蹤敗露之前,要儘快完成巫妖王交給你的任務。
題目描述
軍團是一個 nn 行 mm 列的矩陣,每個單元是一個血色先鋒軍的成員。感染瘟疫的人,每過一個小時,就會向四周擴散瘟疫,直到所有人全部感染上瘟疫。你已經掌握了感染源的位置,任務是算出血色先鋒軍的領主們感染瘟疫的時間,並且將它報告給巫妖王,以便對血色先鋒軍進行一輪有針對性的圍剿。
輸入格式
第 11 行:四個整數 nn,mm,aa,bb,表示軍團矩陣有 nn 行 mm 列。有 aa 個感染源,bb 為血色敢死隊中領主的數量。
接下來 aa 行:每行有兩個整數 xx,yy,表示感染源在第 xx 行第 yy 列。
接下來 bb 行:每行有兩個整數 xx,yy,表示領主的位置在第 xx 行第 yy
列。輸出格式
第 11 至 bb 行:每行一個整數,表示這個領主感染瘟疫的時間,輸出順序與輸入順序一致。如果某個人的位置在感染源,那麼他感染瘟疫的時間為 00。
輸入輸出樣例
輸入 #1複製
5 4 2 3 1 1 5 4 3 3 5 3 2 4
輸出 #1複製
3 1 3
說明/提示
輸入輸出樣例 1 解釋
如下圖,標記出了所有人感染瘟疫的時間以及感染源和領主的位置。
資料規模與約定
對於 100%100% 的資料,保證 1\le n,m\le5001≤n,m≤500,1\le a,b\le10^51≤a,b≤105。
多次bfs
分析
每次讀到一個感染源,就從該感染源出發進行bfs
需要注意的是,第一次bfs之前先將距離陣列初始化成INF,然後根據是不是能更新一個點的最小距離來判斷是否將該點入隊。
程式碼
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 510;
int dist[N][N];
bool st[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
int n, m, a, b;
void bfs(int x, int y)
{
memset(st, 0, sizeof st);
queue<PII> q;
q.push({x, y});
st[x][y] = true;
dist[x][y] = 0;
while(q.size())
{
PII tmp = q.front();
q.pop();
int x = tmp.first, y = tmp.second;
for(int i = 0; i < 4; i++)
{
int nx = x + dx[i], ny = y + dy[i];
if(nx >= 0 && nx < n && ny >= 0 && ny < m && !st[nx][ny])
{
if(dist[nx][ny] > dist[x][y] + 1)
{
st[nx][ny] = true;
dist[nx][ny] = dist[x][y] + 1;
q.push({nx, ny});
}
}
}
}
}
int main()
{
memset(dist, 0x3f, sizeof dist); // 第一次bfs之前
scanf("%d%d%d%d", &n, &m, &a, &b);
while(a --)
{
int x, y;
scanf("%d%d", &x, &y);
bfs(x-1, y-1);
}
while(b --)
{
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", dist[x-1][y-1]);
}
return 0;
}