[HAOI2008] 移动玩具 - BFS

Posted mollnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HAOI2008] 移动玩具 - BFS相关的知识,希望对你有一定的参考价值。

在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移动到某人心中的目标状态。

Solution

考虑到状态可以被压成一个 (leq 65535) 的数,状态压缩以后暴力记忆化搜索即可

#include <bits/stdc++.h>
using namespace std;

int f[65536];
queue <int> q;
char s[5][5];
int from,to;

int get(int p,int i,int j) {
    return (p>>(i*4+j))&1;
}

int put(int p,int i,int j) {
    return p|(1<<(i*4+j));
}

int iput(int p,int i,int j) {
    return p&(~(1<<(i*4+j)));
}

void solve(int p,int i,int j,int ii,int jj) {
    if(ii>=0 && jj>=0 && ii<4 && jj<4 && get(p,ii,jj)==0) {
        int t=put(iput(p,i,j),ii,jj);
        if(f[t]>f[p]+1) {
            f[t]=f[p]+1;
            q.push(t);
        }
    }
}

signed main() {
    for(int i=0;i<4;i++) cin>>s[i];
    for(int i=0;i<4;i++) for(int j=0;j<4;j++) if(s[i][j]=='1') from=put(from,i,j);
    for(int i=0;i<4;i++) cin>>s[i];
    for(int i=0;i<4;i++) for(int j=0;j<4;j++) if(s[i][j]=='1') to=put(to,i,j);
    q.push(from);
    memset(f,0x3f,sizeof f);
    f[from]=0;
    while(!q.empty()) {
        int p=q.front(); q.pop();
        for(int i=0;i<4;i++) {
            for(int j=0;j<4;j++) {
                if(get(p,i,j)) {
                    solve(p,i,j,i,j-1);
                    solve(p,i,j,i,j+1);
                    solve(p,i,j,i-1,j);
                    solve(p,i,j,i+1,j);
                }
            }
        }
    }
    cout<<f[to];
}

以上是关于[HAOI2008] 移动玩具 - BFS的主要内容,如果未能解决你的问题,请参考以下文章

P4289 [HAOI2008]移动玩具

[HAOI2008]移动玩具

[HAOI2008]移动玩具

位运算BFS移动玩具

HAOI2008 移动玩具

bzoj1054[HAOI2008]移动玩具