G. To Go Or Not To Go?(Codeforces Round #719 (Div. 3)题解)

题目链接:G. To Go Or Not To Go?
思路:我们发现最优解最多只需要走一次传送门,于是bfs遍历与\((n,m)\)相连的联通块,求出所有传送门到终点中,所需要的花费,因为两个传送门之前传送所需要\(a_{i,j}+a_{x,y}\)所以我们可以将它分开计算(前后两部分相互不影响),我们把\(a_{x,y}\)计算到该花费中,可以得出来一个最小花费的传送门,然后相同的操作去求与\((1,1)\)相连的联通块,当然如果\((1,1),(n,m)\)相连,那么可以顺带求得他们不用传送门的最小花费,最终答案就是走一次传送门和不走传送门花费的最小值;
\(Code:\)

#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#define ch() getchar()
#define pc(x) putchar(x)
#include<stack>
#include<unordered_map>
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define ll long long
#define ull unsigned long long
#define pb emplace_back
#define mp make_pair
#define PI acos(-1)
using namespace std;
template<typename T>void read(T&x){
    static char c;
    static int f;
    for(c=ch(),f=1; c<'0'||c>'9'; c=ch())if(c=='-')f=-f;
    for(x=0; c>='0'&&c<='9'; c=ch())x=x*10+(c&15);
    x*=f;
}
template<typename T>void write(T x){
    static char q[65];
    int cnt=0;
    if(x<0)pc('-'),x=-x;
    q[++cnt]=x%10,x/=10;
    while(x)
        q[++cnt]=x%10,x/=10;
    while(cnt)pc(q[cnt--]+'0');
}


const int N = 2e3+10;
int n,m;
ll w;
ll a[N][N];
int l[] = {-1,1,0,0},r[] = {0,0,-1,1};
bool st[N][N];
pair<int,int> q[N*N];
struct node{
    int x,y;
    ll val;
}mi0,mi;
ll ans = 1e18+1;
ll d[N][N];
void bfs(int x,int y,int type){
    int hh = 0,tt = -1;
    q[++tt] = {x,y};
    st[x][y] = true;
    d[x][y] = 0;
    if(a[x][y]){
        ll now = a[x][y];
        if(type == 1)mi = {x,y,now};
        else mi0 = {x,y,now};
    }
    while(hh<=tt){
        int xx = q[hh].first,yy = q[hh].second;
        hh++;
        rep(i,0,3){
            int idx = xx + l[i],idy = yy + r[i];
            if(idx > n or idx < 1 or idy > m or idy < 1)continue;
            if(st[idx][idy])continue;
            if(a[idx][idy] == -1)continue;
            st[idx][idy] = true;
            d[idx][idy] = d[xx][yy] + w;
            if(a[idx][idy]){
                ll now = a[idx][idy] + d[idx][idy];
                if(now < mi.val and type == 1)mi = {idx,idy,now};
                else if(now < mi0.val and type == 0)mi0 = {idx,idy,now};
            }
            q[++tt] = {idx,idy};
            if(idx == 1 and idy == 1 and type == 1)ans = min(ans,d[1][1]);
        }
    }
    return ;
}
void solve(){
        mi = {-1,-1,(ll)1e18+1};
        mi0 = mi;
        read(n);read(m);read(w);
        rep(i,1,n){
            rep(j,1,m){
                read(a[i][j]);
            }
        }
        bfs(n,m,1);
        memset(st,0,sizeof st);
        bfs(1,1,0);
        if((mi.x == -1 or mi0.x == -1) and ans == 1e18+1){
            write(-1);
        } else {
            //printf("%lld \n",mi.val+mi0.val);
            ans = min(ans,mi.val+mi0.val);
            write(ans);
        }
        pc('\n');

}


signed main(){solve();return 0; }



posted @ 2021-06-03 17:29  xiaodangao  阅读(108)  评论(0编辑  收藏  举报