题解:洛谷 P11454([USACO24DEC] 2D Conveyer Belt S)
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;
}

浙公网安备 33010602011771号