题解:P14402 [JOISC 2016] 危险的滑冰 / Dangerous Skating
KingGojianOfYue · · 题解
模拟赛题,赛时由于糖了写了个
首先,显然可以通过耗费
然后,直接跑最短路就可以过了?
浅证一下:如果你想到达一个格子,那么这个格子相邻肯定有冰块,所以你就只能来回挪;如果这是一个新的有冰块的格子,那么你要再次利用它需要至少
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
constexpr int N=1e3+5;
char s[N][N];
int dis[N][N],sx,sy,tx,ty;
int vis[N][N],L[N][N],R[N][N],U[N][N],D[N][N];
struct node{
int i,j;
};
vector<node>e[N*N];
inline void solve(){
cin>>n>>m;
for(int i=1;i<=n;++i)cin>>s[i];
cin>>sx>>sy>>tx>>ty;
memset(dis,0x3f,sizeof(dis));
e[0].emplace_back((node){sx,sy});
for(int i=1;i<=n;++i){
for(int j=m;j>=1;--j)s[i][j]=s[i][j-1];
for(int j=1,now=1;j<=m;++j){
if(s[i][j]=='#')now=j+1;
else L[i][j]=now;
}
for(int j=m,now=m;j>=1;--j){
if(s[i][j]=='#')now=j-1;
else R[i][j]=now;
}
}
for(int i=1;i<=m;++i){
for(int j=1,now=1;j<=n;++j){
if(s[j][i]=='#')now=j+1;
else U[j][i]=now;
}
for(int j=n,now=n;j>=1;--j){
if(s[j][i]=='#')now=j-1;
else D[j][i]=now;
}
}
int di=0;
while(1){
while(di<=n*m&&e[di].empty())++di;if(di>n*m)break;
node u=e[di].back();e[di].pop_back();
if(vis[u.i][u.j])continue;
if(u.i==tx&&u.j==ty){cout<<di;return;}
vis[u.i][u.j]=1;
if(s[u.i][u.j-1]=='.'){
if(dis[u.i][L[u.i][u.j]]>di+1)dis[u.i][L[u.i][u.j]]=di+1,e[di+1].emplace_back((node){u.i,L[u.i][u.j]});
if(dis[u.i][u.j-1]>di+2)dis[u.i][u.j-1]=di+2,e[di+2].emplace_back((node){u.i,u.j-1});
}
if(s[u.i][u.j+1]=='.'){
if(dis[u.i][R[u.i][u.j]]>di+1)dis[u.i][R[u.i][u.j]]=di+1,e[di+1].emplace_back((node){u.i,R[u.i][u.j]});
if(dis[u.i][u.j+1]>di+2)dis[u.i][u.j+1]=di+2,e[di+2].emplace_back((node){u.i,u.j+1});
}
if(s[u.i-1][u.j]=='.'){
if(dis[U[u.i][u.j]][u.j]>di+1)dis[U[u.i][u.j]][u.j]=di+1,e[di+1].emplace_back((node){U[u.i][u.j],u.j});
if(dis[u.i-1][u.j]>di+2)dis[u.i-1][u.j]=di+2,e[di+2].emplace_back((node){u.i-1,u.j});
}
if(s[u.i+1][u.j]=='.'){
if(dis[D[u.i][u.j]][u.j]>di+1)dis[D[u.i][u.j]][u.j]=di+1,e[di+1].emplace_back((node){D[u.i][u.j],u.j});
if(dis[u.i+1][u.j]>di+2)dis[u.i+1][u.j]=di+2,e[di+2].emplace_back((node){u.i+1,u.j});
}
}
cout<<-1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
solve();
return 0;
}