Codeforces gym101755H Safe Path(bfs)

题意:

给以一个网格图,有起点终点和一些怪兽,可以上下左右走,不能走到距离怪兽曼哈顿距离为d以内的地方,问到终点最短路径

n*m<=2e5,d<=2e5

思路:

因为n*m的范围,不能直接建2e5*2e5的图,所以要vector.resize()

如果对每个怪兽都预处理的话,复杂度将是O(d2)

所以我们可以让所有怪兽同时走,这样预处理只有O(nm),也可以证明不会漏情况

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>

#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x))

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 1e6+100;
const int maxm = 1e6+100;
//const int inf = 0x3f3f3f3f;
const int inf = 1e9+7;
const db pi = acos(-1.0);

vector<char>a[maxn];
vector<int>v[maxn],vis[maxn],wall[maxn],tp[maxn];
int n,m,d;
int dx[5] = {0,-1,0,1};
int dy[5] = {1,0,-1,0};
bool ck(int x, int y){
    if(x>=1&&x<=n&&y>=1&&y<=m)return true;
    return false;
}
queue<pair<PI, int>>seetq;
void seet(){

    while(!seetq.empty()){
        auto top = seetq.front();
        seetq.pop();
        int x = top.fst.fst;
        int y = top.fst.sc;
        int z = top.sc;
        //f(v[x][y])continue;
        //v[x][y]=1;
        if(z==d)continue;
        for(int i = 0; i < 4; i++){
            if(ck(x+dx[i],y+dy[i])&&v[x+dx[i]][y+dy[i]]==0){
                seetq.push({{x+dx[i],y+dy[i]},z+1});
                v[x+dx[i]][y+dy[i]]=1;
            }
        }
    }
    return;
}
PI s,t;
char str[maxn];

int main() {
    scanf("%d %d %d", &n, &m, &d);
    for(int i = 1; i <= n; i++){
        v[i].resize(m+1);
        a[i].resize(m+1);
        vis[i].resize(m+1);
        wall[i].resize(m+1);
        tp[i].resize(m+1);
    }

    //getchar();
    for(int i = 1; i <= n; i++){
        scanf("%s",str+1);
        for(int j = 1; j <= m; j++){
            v[i][j]=vis[i][j]=wall[i][j]=0;
            tp[i][j]=inf;
            char c = str[j];
            a[i][j] = c;
            if(c==‘S‘){
                s = {i,j};
            }
            else if(c==‘F‘){
                t = {i,j};
            }
            else if(c==‘M‘){
                wall[i][j]=d+1;
                seetq.push({{i,j},0});
                v[i][j]=1;
            }
        }
    }
    seet();
    queue<pair<PI,int>>q;
    q.push({{s.fst,s.sc},0});
    int ans = -1;
    if(v[s.fst][s.sc]==1)return printf("-1"),0;
    q.push({{s.fst,s.sc},0});
    while(!q.empty()){
        auto top = q.front();
        q.pop();
        int x = top.fst.fst;
        int y = top.fst.sc;
        int z = top.sc;
        if(x==t.fst&&y==t.sc){
            ans=z;
            break;
        }
        if(vis[x][y])continue;
        vis[x][y]=1;
        for(int i = 0; i < 4; i++){
            int nx = x+dx[i];
            int ny = y+dy[i];
            if(ck(nx,ny)&&vis[nx][ny]==0&&v[nx][ny]!=1){
                q.push({{nx,ny},z+1});
            }
        }
    }
    printf("%d",ans);
    return 0;
}
/*
4
2 2 3
2 3 4
1 4
0
 */

原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10757404.html

时间: 2024-08-30 07:41:31

Codeforces gym101755H Safe Path(bfs)的相关文章

codeforces 1072D Minimum path bfs+剪枝 好题

题目传送门 题目大意: 给出一幅n*n的字符,从1,1位置走到n,n,会得到一个字符串,你有k次机会改变某一个字符(变成a),求字典序最小的路径. 题解: (先吐槽一句,cf 标签是dfs题????) 这道题又学到了,首先会发现,从原点出发,走x步,所有的情况都是在一条斜线上的,而再走一步就是下一条斜线.所以用两个队列进行bfs(把当前步和下一步要处理的字符分开). 到了这里思路就明朗了,每次走的时候如果本身的map里是a就直接走,不是a就看k是否大于0,再看这个字符是不是比答案串里对应位置的字

Codeforces 429B Working out bfs构造

题目链接:点击打开链接 题意:给定n*m的矩阵 有一个人a从左上角走到右下角,只能↓或→走 另一个人b从左下角走到右上角,只能↑或→走 使得2个人的路径有且仅有一个格子是相交的. 统计2个人的权值和(相交格子的权值和不计) 问最大的权值和是多少. 思路: 首先转换一下题意,也就是找一个格子与4个角落连不相交的线. 我们观察相交的那个格子,那个格子的上下左右必然对应着一个角落. (i,j)点,那么(i-1,j)必然对应左上角或右上角的其中一个角落. 这样(i,j)点的4个相邻格子各自对应一个角落(

Safe Path(bfs+一维数组存图)

题目链接:http://codeforces.com/gym/101755/problem/H 题目分析:先bfs一遍怪兽可以到达的点,再bfs人可以走的地方看可不可以到达终点: 很显然读到  2<=n*m<=200000 时,就不可以用二维数组存图了,不过据说因为数据比较水,可以用vector存图: vector存图AC代码: 1 /* */ 2 # include <iostream> 3 # include <stdio.h> 4 # include <st

poj 3126 Prime Path (bfs)

Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13813   Accepted: 7796 Description The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-dig

Prime Path bfs搞定

The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices. — It is a matter of security to change such things every now and then, to

POJ 3126 Prime Path(BFS 数字处理)

题意  给你两个4位素数a, b  你每次可以改变a的一位数但要求改变后仍为素数  求a至少改变多少次才能变成b 基础的bfs  注意数的处理就行了  出队一个数  然后入队所有可以由这个素数经过一次改变而来的素数  知道得到b #include <cstdio> #include <cstring> using namespace std; const int N = 10000; int p[N], v[N], d[N], q[N], a, b; void initPrime(

HDU 6223 Infinite Fraction Path(BFS+剪枝)

The ant Welly now dedicates himself to urban infrastructure. He came to the kingdom of numbers and solicited an audience with the king. He recounted how he had built a happy path in the kingdom of happiness. The king affirmed Welly's talent and hoped

[POJ]P3126 Prime Path[BFS]

[POJ]P3126 Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 35230   Accepted: 18966 Description The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change

CodeForces 762D Maximum path

http://codeforces.com/problemset/problem/762/D 因为是3*n很巧妙的地方是 往左走两步或更多的走法都可以用往回走以一步 并走完一列来替换 那么走的方法就大大减少 左边一列转移到右边一列 每个 格子的转移方法枚举出来 用动态规划即可解决 最主要的是因为他能够往回走.但是我们画图可以发现:每次往回走一定不用超过1次.也就是说,最多只能走成这样 而不会走成这样 因为下图的走法一定可以用上图组合,并且由于只用3行的特性,每次向回走实际上是取走了所有的数.所以