思路正确,代码看上去正确,但是卡在20分
查看原帖
思路正确,代码看上去正确,但是卡在20分
536337
eb0ycn楼主2024/8/23 21:19
/*
思路:先预处理传送到第i个传送门的最少耗时,这里以传送门起点为bfs起点跑多源最短路。
预处理后再跑bfs,算上不走传送门的情况。 
*/
#include<bits/stdc++.h>
using namespace std;
const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
char s[1002][1002];
int n,m,p,q,op,dis[1001][1001],sx,sy,tx[1000001],ty[1000001],x,y,ex,ey,nx,ny,l,r,Q[1000001][2],d[1000001],now,step;
//tx,ty是q个传送门起点的坐标。
//sx sy是起点,ex ey是终点。
//l r Q是手写队列用的东西。
//d[i]是传送到第 i 个传送门终点的最小耗时。
inline bool ck(int a,int b){return a&&b&&a<=n&&b<=m&&s[a][b]=='.';}
//检验一个位置是否合法。 
void bfs(){
	while(l<r){
		x=Q[++l][0],y=Q[l][1];
		for(int i=0;i<4;++i){
			nx=x+dx[i],ny=y+dy[i];
			if(ck(nx,ny)&&dis[x][y]+1<dis[nx][ny])
				dis[nx][ny]=dis[x][y]+1,Q[++r][0]=nx,Q[r][1]=ny;
		}//预处理到某个传送门的最少耗时。
	}
}
void cfs(){
	while(l<r){
		x=Q[++l][0],y=Q[l][1],step=dis[x][y];
		while(now<=q&&d[now]<=step+1){
			if(d[now]<dis[tx[now]][ty[now]])
				dis[tx[now]][ty[now]]=d[now],Q[++r][0]=tx[now],Q[r][1]=ty[now];
			++now;
		}//如果走传送门更优,就走。这里 d[now]<=step+1是为了保持队列单调性。

		for(int i=0;i<4;++i){
			nx=x+dx[i],ny=y+dy[i];
			if(ck(nx,ny)&&dis[x][y]+1<dis[nx][ny])
				dis[nx][ny]=dis[x][y]+1,Q[++r][0]=nx,Q[r][1]=ny;
		}//普通的走法。
		if(now<=q&&l==r){
			if(d[now]<dis[tx[now]][ty[now]])
				Q[++r][0]=tx[now],Q[r][1]=ty[now],dis[tx[now]][ty[now]]=d[now];
			++now;
		}//如果队列为空,也要请出走传送门的情况了。
		//否则如果起点和终点被隔开了只能走传送门,不考虑这种情况就会爆。
	}
}
int main(){
	scanf("%d%d%d",&op,&n,&m);
	for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
	for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)dis[i][j]=0x3f3f3f3f;
	scanf("%d%d%d%d",&sx,&sy,&p,&q);
	if(op)scanf("%d%d",&ex,&ey);
	for(int i=1;i<=p;++i)scanf("%d%d",&x,&y),dis[x][y]=0,Q[++r][0]=x,Q[r][1]=y;
	bfs(),l=r=0;
	for(int i=1;i<=q;++i)scanf("%d%d",tx+i,ty+i);
	d[1]=dis[sx][sy];
	for(int i=2;i<=q;++i)d[i]=d[i-1]==0x3f3f3f3f?0x3f3f3f3f:d[i-1]+dis[tx[i-1]][ty[i-1]];
	for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)dis[i][j]=0x3f3f3f3f;
	now=1,dis[sx][sy]=0,Q[++r][0]=sx,Q[r][1]=sy,cfs();
	if(op)printf("%d",dis[ex][ey]==0x3f3f3f3f?-1:dis[ex][ey]);
	else{
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j)printf("%d ",dis[i][j]==0x3f3f3f3f?-1:dis[i][j]);
			printf("\n");
		}
	}
	return 0;
}
2024/8/23 21:19
加载中...