【BFS】题目积累
【BFS】题目积累
BFS更适用于扩展性的题目:由几个原始点往外拓展
DFS更适用于遍历性的题目:一条分支走到结束再回头
No Passage
属于题目大意比较难懂的那一类
https://atcoder.jp/contests/abc413/tasks/abc413_f
题目大意
nxm的棋盘,若干个目标点
考虑棋盘中每一个位置,统计每一个位置走到任一目标点的最短步数的和
如果走不到,最短步数为0
规定目标点最短步数也为0
有一个特殊规则:先手在每一步都可以封掉一个方向,后手走不了这个方向
思路
每次先手都可以挡住后手的一条路->一个空白点一定要至少能到达2个目标点
->数据范围考虑bfs
把所有目标点(in为2的点)放到队列里 一个点至少要被bfs到2次
->最小距离?
当已经被bfs到2次之后的val值就是最小值
代码
const int N=3010;
int n,m,k;
int in[N][N];
i64 ans[N][N];
void solve(){
cin>>n>>m>>k;
queue<array<int,3>> q;
for(int i=1;i<=k;i++){
int r,c;
cin>>r>>c;
in[r][c]=2;
q.push({r,c,0});
}
while(q.size()){
auto [x,y,val]=q.front();
q.pop();
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) continue;
if(in[nx][ny]==2) continue;
in[nx][ny]++;
if(in[nx][ny]==2){//更新答案
ans[nx][ny]=(i64)(val+1LL);
q.push({nx,ny,val+1});
}
}
}
i64 an=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
an+=ans[i][j];
}
}
cout<<an<<endl;
}