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; }