Stronger Takahashi
Stronger Takahashi
题意:
从(1,1)走到(h,w)的最短耗费,s(i,j)为‘.’表示可走,为‘#’表示有阻挡物,我们可以耗费1去打通一个相邻2*2的方块,无论这个方块是否可以走通都可以变成能走通
思路:建图+spfa最短路
假设他在需要之前不打孔,我们可以假设一个2×2破坏块区域与高桥所在的正方形相邻。当高桥位于下图中标记的T的正方形中时,在打孔一次后,他可以移动到标记为*的任何正方形,不管方块的先前状态如何。
.***.
*****
**T**
*****
.***.
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=250010;
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
int f[N],dis[N],vis[N];
int h,w,cnt,id;
int p[510][510];
char c[510][510];
int e[N<<5],ww[N<<5],ne[N<<5];
void add(int x,int y,int v){
e[++id]=x;
ww[id]=v;
ne[id]=f[y];
f[y]=id;
}
bool check(int x,int y){
if(x>h||x<1||y>w||y<1) return false;
return true;
}
struct cmp
{
bool operator()(int a,int b)
{
return dis[a]>dis[b];
}
};
void spfa(){
vis[1]=1;
priority_queue<int,vector<int>,cmp> q;
q.push(1);
dis[1]=0;
while(q.size()){
int t=q.top();
q.pop();
vis[t]=0;
for(int i=f[t];~i;i=ne[i]){
int k=e[i];
if(dis[k]>dis[t]+ww[i]){
dis[k]=dis[t]+ww[i];
if(vis[k]==0){
q.push(k);
vis[k]=1;
}
}
}
}
}
signed main(){
memset(f,-1,sizeof f);
memset(vis,0,sizeof vis);
memset(dis,0x3f,sizeof dis);
cin>>h>>w;
for(int i=1;i<=h;i++){
for(int j=1;j<=w;j++){
cin>>c[i][j];
p[i][j]=++cnt;
}
}
for(int i=1;i<=h;i++){
for(int j=1;j<=w;j++){
//表示周围是可行的,费用为0
for(int k=0;k<4;k++){
int xx=i+dx[k],yy=j+dy[k];
if(check(xx,yy)&&c[xx][yy]!='#'){
add(p[xx][yy],p[i][j],0);
}
}
//表示在这个点打了墙费用为1
for(int k=-2;k<=2;k++){
for(int kk=-2;kk<=2;kk++){
if(abs(k)==2&&abs(kk)==2) continue;
int xx=i+k,yy=j+kk;
if(check(xx,yy)){
add(p[xx][yy],p[i][j],1);
}
}
}
}
}
spfa();//跑最短路
cout<<dis[p[h][w]]<<endl;
}

浙公网安备 33010602011771号