题解:洛谷 P11454([USACO24DEC] 2D Conveyer Belt S)

Link

1. Description

原题面的释义十分清楚,搭配样例食用更佳。

2. Solution

首先考虑一个已经确定的方阵怎么求解,可以使用 bfs。

显然,我们从方阵的四边开始 bfs,当一个位置没有修建过传送带,或者通过这个位置已经修建的传送带可以传送出方阵的话,这个位置合法,可以作为起点。bfs 通过 \((x,y)\) 向四周拓展时,可以拓展到的位置和确定起点的条件类似,要么拓展到的位置没有修建过传送带,要么可以通过这个位置已经修建的传送带到达 \((x,y)\)

由此,我们获得了暴力做法,每一次都暴力 bfs 求解答案,时间复杂度为 \(O(qn^2)\)

考虑优化,对于增加一个传送带的情况,会使一些原本可用的位置变得不可用,但是这是不好判断的,所以我们考虑反向来做,首先求出最后的情况的答案,然后依次删除传送带,显然,一个位置删除传送带之后合法的情况有限,要么这个位置本来就合法,此时直接跳过,要么这个位置本来在边界上,要么这个位置四周有一个合法的位置,然后以这个位置为起点进行 bfs,拓展时注意:已经合法的位置不再遍历。

由于所有位置在删除传送带后不会从合法变得不合法,所以所有位置只会被遍历依次,时间复杂度为 \(O(n^2+q)\)

3. Code

/*by qwer6*/
/*略去缺省源和快读快写*/
const int N=1005,M=2e5+5,dx[]={1,-1,0,0},dy[]={0,0,1,-1}; 
int n,m;
int ans[M];
char c[N][N];
struct Query{
	int x,y;
	char opt;
}b[M];
struct Queue{
	int res;
	bool vis[N][N];
	queue<pii>q;
	bool check(int x,int y){
		return 1<=x&&x<=n&&1<=y&&y<=n&&vis[x][y]==0;
	}
	void push(int x,int y){
		vis[x][y]=1;
		res++;
		q.push({x,y});
	}
	pii front(){
		return q.front();
	}
	bool empty(){
		return q.empty();
	}
	void pop(){
		return q.pop();
	}
}q;
void bfs(){
	while(!q.empty()){
		int x=q.front().first,y=q.front().second;
		q.pop();
		if(q.check(x-1,y))
			if(c[x-1][y]=='?'||c[x-1][y]=='D')
				q.push(x-1,y);
		if(q.check(x+1,y))
			if(c[x+1][y]=='?'||c[x+1][y]=='U')
				q.push(x+1,y);
		if(q.check(x,y-1))
			if(c[x][y-1]=='?'||c[x][y-1]=='R')
				q.push(x,y-1);
		if(q.check(x,y+1))
			if(c[x][y+1]=='?'||c[x][y+1]=='L')
				q.push(x,y+1);
	}
}
void init(){
	for(int i=2;i<n;i++){
		//第 1 行的位置 
		if(c[1][i]=='?'||c[1][i]=='U')
			q.push(1,i);
		//第 n 行的位置  
		if(c[n][i]=='?'||c[n][i]=='D')
			q.push(n,i);
		//第 1 列的位置 
		if(c[i][1]=='?'||c[i][1]=='L')
			q.push(i,1);
		//第 n 列的位置 
		if(c[i][n]=='?'||c[i][n]=='R')
			q.push(i,n);
	}
	if(c[1][1]=='?'||c[1][1]=='U'||c[1][1]=='L')
		q.push(1,1);
	if(c[1][n]=='?'||c[1][n]=='U'||c[1][n]=='R')
		q.push(1,n);
	if(c[n][1]=='?'||c[n][1]=='D'||c[n][1]=='L')
		q.push(n,1);
	if(c[n][n]=='?'||c[n][n]=='D'||c[n][n]=='R')
		q.push(n,n);
}
bool check(int x,int y){
	for(int i=0,xx,yy;i<4;i++){
		xx=x+dx[i],yy=y+dy[i];
		if(xx<1||xx>n)return true;
		if(yy<1||yy>n)return true;
		if(q.vis[xx][yy])return true;
	}
	return false;
}
signed main(){
	read(n),read(m);
	if(n==1){
		for(int i=1;i<=m;i++)
			puts("0");
		exit(0);
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			c[i][j]='?';
	for(int i=1;i<=m;i++){
		read(b[i].x),read(b[i].y);
		b[i].opt=getchar();
		while(b[i].opt!='U'&&b[i].opt!='D'&&b[i].opt!='L'&&b[i].opt!='R')b[i].opt=getchar();
		c[b[i].x][b[i].y]=b[i].opt;
	}
	init();
	bfs();
	ans[m]=q.res;
	for(int i=m;i>=1;i--){ 
		c[b[i].x][b[i].y]='?';
		if(q.vis[b[i].x][b[i].y]){
			ans[i-1]=ans[i];
			continue;
		}
		if(check(b[i].x,b[i].y)){
			q.push(b[i].x,b[i].y);
			bfs();
			ans[i-1]=q.res;
		}else ans[i-1]=ans[i];
	}
	for(int i=1;i<=m;i++)write(n*n-ans[i]),Nxt;
}
posted @ 2025-05-04 10:23  陈牧九  阅读(26)  评论(0)    收藏  举报