luogu p7284 [COCI2020-2021#4] Patkice II
Netflix 的经商人员想要制作一个有关三只鸭子之旅的系列改编。
在 COCI20/21 的第一轮中,鸭子们位于一个洋流的地图中,鸭子们一同出行。鸭子们的起始岛屿用
o表示。鸭子们可以往四个方向进行旅行,分别是:西 \(\to\) 东(>),东 \(\to\) 西(<),北 \(\to\) 南(v) 和南 \(\to\) 北(^)。当鸭子们位于洋流的点上时,它们将会向洋流的方向移动一个单位。平静的海面用
.表示。如果洋流把鸭子们带到了平静的海面、到达地图之外或者回到起始小岛处,它们就会停止旅行。鸭子们想要前往的目的地岛屿用x表示。为了让情节更加吸引人,Netflix 进行了改编:现在海面上可能会出现旋涡(鸭子们可能会困在其中)和可把鸭子带到地图之外的洋流。
因此,原先地图被迫改变。但在即将到来的截止期的情况下,导演犯了几个错误:鸭子们不能再通过洋流到达目的地岛屿。
Netflix 导演是非常重要的人,因此他们并不花时间思考情节漏洞。你的任务是替换地图中的几个字符,使得鸭子们能够从起始岛屿到达目的地岛屿。
因情节需要,字符
o和x不能被修改。其他字符(<>v^.)分别表示洋流和平静的海面。你可以用<>v^中的任意字符来替换原先地图中<>v^. 的任意字符。需要输出方案 .
\(1\leq n,m\leq 2000\)
考虑最短路 .
\(dis(i,j)\) 表示从起点到 \((i,j)\) 最少需要修改多少个字符 .
那么,直接考虑当前以为是否修改,修改就增加 \(1\) 的代价,不修改代价就为 \(0\) .
现在就有一个问题,一个位置是否会被修改两次 .
分析一下,发现,如果被修改了两次,肯定不如第一次直接修改到第二次想到的字符上优秀 .
所以,这样做肯定只会修改一次 ,是可行的 .
直接跑 dijkstra 或 01bfs 即可 . 因为要输出方案,所以要记录一下路径 .
时间复杂度 : \(O(nm\log nm)\)
空间复杂度 : \(O(nm)\)
code
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9+10;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
int n,m;
char a[4010][4010],ans[4010][4010];
int dis[4010][4010];
pair<int,int>sol[4010][4010];
priority_queue<pair<int,int> >q;
inline int get_id(int x,int y){return x*m+y;}
void get_ans(int x,int y){
if(sol[x][y].first==-1)return;
int nx=sol[x][y].first,ny=sol[x][y].second;
if(x==nx-1)ans[nx][ny]='^';
if(x==nx+1)ans[nx][ny]='v';
if(y==ny-1)ans[nx][ny]='<';
if(y==ny+1)ans[nx][ny]='>';
get_ans(nx,ny);
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=0;i<n;i++)for(int j=0;j<m;j++)cin>>a[i][j];
int sx,sy,tx,ty;
for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(a[i][j]=='o')sx=i,sy=j;
for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(a[i][j]=='x')tx=i,ty=j;
for(int i=0;i<4010;i++)for(int j=0;j<4010;j++)dis[i][j]=inf;
for(int i=0;i<4010;i++)for(int j=0;j<4010;j++)sol[i][j]=make_pair(-1,-1);
dis[sx][sy]=0;
for(int i=0;i<4;i++){
int x=sx+dx[i],y=sy+dy[i];
if(x>=0&&x<n&&y>=0&&y<m){
dis[x][y]=0;
q.push(make_pair(-dis[x][y],get_id(x,y)));
}
}
while(!q.empty()){
int cost=-q.top().first,x=q.top().second/m,y=q.top().second%m;
q.pop();
if(cost>dis[x][y])continue;
if(a[x][y]=='x')continue;
// cout<<x<<" "<<y<<" "<<dis[x][y]<<endl;
if(a[x][y]=='^'){
if(x-1>=0&&dis[x-1][y]>dis[x][y]){
dis[x-1][y]=dis[x][y];
sol[x-1][y]=make_pair(x,y);
q.push(make_pair(-dis[x-1][y],get_id(x-1,y)));
}
}
if(a[x][y]=='v'){
if(x+1<n&&dis[x+1][y]>dis[x][y]){
dis[x+1][y]=dis[x][y];
sol[x+1][y]=make_pair(x,y);
q.push(make_pair(-dis[x+1][y],get_id(x+1,y)));
}
}
if(a[x][y]=='<'){
if(y-1>=0&&dis[x][y-1]>dis[x][y]){
dis[x][y-1]=dis[x][y];
sol[x][y-1]=make_pair(x,y);
q.push(make_pair(-dis[x][y-1],get_id(x,y-1)));
}
}
if(a[x][y]=='>'){
if(y+1<m&&dis[x][y+1]>dis[x][y]){
dis[x][y+1]=dis[x][y];
sol[x][y+1]=make_pair(x,y);
q.push(make_pair(-dis[x][y+1],get_id(x,y+1)));
}
}
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx>=0&&nx<n&&ny>=0&&ny<m){
if(dis[nx][ny]>dis[x][y]+1){
dis[nx][ny]=dis[x][y]+1;
sol[nx][ny]=make_pair(x,y);
q.push(make_pair(-dis[nx][ny],get_id(nx,ny)));
}
}
}
}
cout<<dis[tx][ty]<<endl;
for(int i=0;i<n;i++)for(int j=0;j<m;j++)ans[i][j]='.';
get_ans(tx,ty);
for(int i=0;i<n;i++)for(int j=0;j<m;j++){
if(a[i][j]=='o')ans[i][j]='o';
else if(a[i][j]=='x')ans[i][j]='x';
else if(ans[i][j]=='.')ans[i][j]=a[i][j];
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)cout<<ans[i][j];
cout<<endl;
}
return 0;
}
/*inline? ll or int? size? min max?*/

浙公网安备 33010602011771号