[HAOI2008] 移动玩具
观察到给定的两个方框都是4*4的,能想到记忆化搜索,当然,将记忆化搜索换个顺序就是dp
将每一位是否有玩具用0/1表示,最后生成一个16位的0/1序列,将起点终点的0/1序列处理出来,用类似bfs的方式存下可能对答案有贡献的状态,每一次枚举每一个有玩具的位置,枚举能到达的位置,进行转移。
using namespace std;
#define ll long long
#define MAXN 1<<17
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
ll mp1[5][5],mp2[5][5],dp[MAXN];
ll st,ed;
ll ad_x[4]={0,1,0,-1},ad_y[4]={1,0,-1,0};
ll id(ll x,ll y){
return 1<<((x-1)*4+y-1);
}
int main(){
string s;
for(int i=1;i<=4;i++){
cin>>s;
for(int j=1;j<=4;j++){
mp1[i][j]=s[j-1]-'0';
}
}
for(int i=1;i<=4;i++){
cin>>s;
for(int j=1;j<=4;j++){
mp2[i][j]=s[j-1]-'0';
if(mp2[i][j]&mp1[i][j]){
mp2[i][j]=mp1[i][j]=0;
}
}
}
for(int i=1;i<=4;i++){
for(int j=1;j<=4;j++){
if(mp1[i][j])st|=id(i,j);
}
}
for(int i=1;i<=4;i++){
for(int j=1;j<=4;j++){
if(mp2[i][j])ed|=id(i,j);
}
}
queue<ll> q;
memset(dp,0x3f,sizeof(dp));
dp[st]=0;
q.push(st);
while(!q.empty()){
ll now=q.front();
q.pop();
if(now==ed)break;
// cout<<now<<endl;
for(int x=1;x<=4;x++){
for(int y=1;y<=4;y++){
if(!(now&id(x,y)))continue;
for(int u=0;u<4;u++){
ll _x=x+ad_x[u],_y=y+ad_y[u];
if(_x<1||_x>4||_y<1||_y>4||now&id(_x,_y))continue;
ll p=now^id(_x,_y)^id(x,y);
// cout<<p<<" ";
if(dp[now]+1<dp[p]){
dp[p]=dp[now]+1;
q.push(p);
}
}
}
}
// cout<<"\n------------\n";
}
cout<<dp[ed];
return 0;
}

浙公网安备 33010602011771号