思路:如果一个点上存在领主,那么从这个点开始广搜,搜到最近的感染源,将该点上所有领主的感染时间进行更新。许多点都是七八百毫秒过去的,看了题解我的思路似乎是错的,但为什么能通过?
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
int n,m,a,b;//四个数字
int xx[] = {1,0,-1,0};
int yy[] = {0,1,0,-1};
vector<int> id[505][505];//存储某个点上的领主
bool map[505][505];//存储感染源
int tim[100005];//感染时间
void bfs(int bx,int by){
if(map[bx][by]) return;//感染源与领主重叠
bool seen[505][505];//标记访问过的节点
int dist[505][505];//存储时间
queue<pair<int,int>> q;
memset(seen,false,sizeof(seen));
q.push({bx,by});
seen[bx][by] = true;
dist[bx][by] = 0;
while(!q.empty()){
int x = q.front().first;
int y = q.front().second;
q.pop();
for(int i = 0;i < 4;i++){
int nx = x + xx[i];
int ny = y + yy[i];
if(nx < 1 || nx > n || ny < 1 || ny > m || seen[nx][ny]) continue;
seen[nx][ny] = true;
dist[nx][ny] = dist[x][y] + 1;
if(map[nx][ny]){//找到感染源,更新
for(int j = 0;j < id[bx][by].size();j++)
tim[id[bx][by][j]] = dist[nx][ny];
return;
}
q.push({nx,ny});
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n >> m >> a >> b;
for(int i = 1;i <= a;i++){
int x,y;
cin >> x >> y;
map[x][y] = true;//输入感染源
}
for(int i = 1;i <= b;i++){
int x,y;
cin >> x >> y;
id[x][y].push_back(i);//输入领主
}
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
if(id[i][j].size() != 0)//size不为0代表有领主
bfs(i,j);
}
}
for(int i = 1;i <= b;i++){
cout << tim[i] << endl;//输出
}
}