α+β Problem
出题人题解。
部分分
子任务
子任务
子任务
子任务
子任务
正解
首先墙壁是诈骗,最优解肯定不用放墙。
假如我们在地图里放了多个箱子,那么这些箱子一定互不影响,即没有把一个箱子推进另一个箱子的情况。
由此我们可以假设地图上放满了箱子,用并查集维护移动过程。
- 左右转对这些箱子没有影响。
- 后退时退到的那一格内的那些箱子都不能放了。
- 前进时如果有把一些箱子推进另一些箱子的情况,直接把面前的箱子合并到更前面的箱子里。
- 注意如果往墙上推就说明面前的那些箱子不能放。
最后在同一连通块的箱子只能放一个,注意箱子要动过的限制后随便选一个即可。
然后发现其实一个连通块只需要记录一个箱子的位置就可以了,于是在合并的时候优先记录被推动的箱子即可。
每组数据时间复杂度为
#include<bits/stdc++.h>
#define CKE if(CHECK)
#define FRE if(FIL)
#define MX 2005
using namespace std;
const int CHECK=0,FIL=0;int read();
bitset<MX*MX> res,p;
int n,m,x,y,X,Y,f,a[MX*MX];string s;
int fx[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
int Z(int i,int j){return i*m-m+j;}
int inMap(int i,int j){return i && j && i<=n && j<=m;}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
FRE freopen(".in","r",stdin);
FRE freopen(".out","w",stdout);
int T;cin>>T;while(T--){
cin>>n>>m>>x>>y>>s>>s;X=x,Y=y,f=0;
for(int i=1;i<=n*m;i++) a[i]=i,res[i]=p[i]=0;
a[Z(x,y)]=0;
for(auto i:s){
if(i=='D') f=(f+1)%4;
if(i=='A') f=(f+3)%4;
if(i=='W'){
int dx=x+fx[f][0],dy=y+fx[f][1];
int wx=dx+fx[f][0],wy=dy+fx[f][1];
if(a[Z(dx,dy)]){
if(inMap(wx,wy)) a[Z(wx,wy)]=a[Z(dx,dy)];
a[Z(dx,dy)]=0,p[Z(dx,dy)]=1;
}
x=dx,y=dy;
}
if(i=='S'){
int dx=x-fx[f][0],dy=y-fx[f][1];
a[Z(dx,dy)]=0;x=dx,y=dy;
}
}
for(int i=1;i<=n*m;i++){
if(!a[i]) continue;
if(p[a[i]]) res[a[i]]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==X && j==Y){cout<<"X"; continue;}
if(res[Z(i,j)]){cout<<"S";}
else cout<<".";
}cout<<'\n';
}
}
return 0;
}
int read(){
int Ca=0;char Cr=' ';int Cf=1;
while(Cr<'0' || Cr>'9'){Cr=getchar();if(Cr=='-'){Cf=-1;}}
while(Cr>='0' && Cr<='9'){Ca=Ca*10+Cr-48;Cr=getchar();}
return Ca*Cf;
}