luogu p7284 [COCI2020-2021#4] Patkice II

Netflix 的经商人员想要制作一个有关三只鸭子之旅的系列改编。

在 COCI20/21 的第一轮中,鸭子们位于一个洋流的地图中,鸭子们一同出行。鸭子们的起始岛屿用 o 表示。鸭子们可以往四个方向进行旅行,分别是:西 \(\to\) 东(>),东 \(\to\) 西(<),北 \(\to\) 南(v) 和南 \(\to\) 北(^)。当鸭子们位于洋流的点上时,它们将会向洋流的方向移动一个单位。

平静的海面用 . 表示。如果洋流把鸭子们带到了平静的海面、到达地图之外或者回到起始小岛处,它们就会停止旅行。鸭子们想要前往的目的地岛屿用 x 表示。

为了让情节更加吸引人,Netflix 进行了改编:现在海面上可能会出现旋涡(鸭子们可能会困在其中)和可把鸭子带到地图之外的洋流。

因此,原先地图被迫改变。但在即将到来的截止期的情况下,导演犯了几个错误:鸭子们不能再通过洋流到达目的地岛屿。

Netflix 导演是非常重要的人,因此他们并不花时间思考情节漏洞。你的任务是替换地图中的几个字符,使得鸭子们能够从起始岛屿到达目的地岛屿。

因情节需要,字符 ox 不能被修改。其他字符(< > 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?*/

posted @ 2021-09-26 10:59  xyangh  阅读(72)  评论(0)    收藏  举报