[HAOI2008]移动玩具

Posted ylwtsq

tags:

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

题目大意:

  给你两个4*4的01矩阵A、B,要求你从矩阵A中将‘1‘移动若干步(移动即与相邻的‘0‘交换位置),变换为B,输出最小步数.

 

基本思路:

  本题数据较小,固定为4*4,第一时间想到状压(2^16),用状压代替hash比较容易.由于要求最小步数,bfs扫描到B矩阵即可输出答案,复杂度远小于dfs.

code:

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#define R register
#define next exnt
#define debug puts("mlg")
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writesp(ll x);
inline void writeln(ll x);
ll ans[65536],n,goal;
bool d[5][5];
inline ll calc(bool M[5][5]){
    ll sum=0;
    for(R ll i=1;i<=16;i++) if(M[(i-1)/4+1][(i-1)%4+1]) sum+=1<<i-1;
    return sum;
}
queue<ll>q;
inline void Bfs(ll now){
    ll To;
    q.push(now);
    while(q.size()){
        now=q.front();q.pop();
        if(now==goal){
            writeln(ans[now]);exit(0);
        }
        for(R ll i=1;i<=16;i++) d[(i-1)/4+1][(i-1)%4+1]=(now&(1<<i-1));
        for(R ll i=1;i<=4;i++){
            for(R ll j=1;j<=4;j++){
                if(d[i][j]){
                    if(i-1>0&&!d[i-1][j]){
                        swap(d[i-1][j],d[i][j]);
                        To=calc(d);
                        if(ans[To]>ans[now]+1){
                            ans[To]=ans[now]+1;
                            q.push(To);
                        }
                        swap(d[i-1][j],d[i][j]);
                    }
                    if(i+1<5&&!d[i+1][j]){
                        swap(d[i+1][j],d[i][j]);
                        To=calc(d);
                        if(ans[To]>ans[now]+1){
                            ans[To]=ans[now]+1;
                            q.push(To);
                        }
                        swap(d[i+1][j],d[i][j]);
                    }
                    if(j-1>0&&!d[i][j-1]){
                        swap(d[i][j-1],d[i][j]);
                        To=calc(d);
                        if(ans[To]>ans[now]+1){
                            ans[To]=ans[now]+1;
                            q.push(To);
                        }
                        swap(d[i][j-1],d[i][j]);
                    }
                    if(j+1<5&&!d[i][j+1]){
                        swap(d[i][j+1],d[i][j]);
                        To=calc(d);
                        if(ans[To]>ans[now]+1){
                            ans[To]=ans[now]+1;
                            q.push(To);
                        }
                        swap(d[i][j+1],d[i][j]);
                    }
                }    
            }
        }
    }
}
int main(){
    for(R ll i=1,x;i<=16;i++){
        char c=getchar();
        while(c!=0&&c!=1) c=getchar();
        x=c-0;
        if(x) n+=1<<i-1;
    }
    memset(ans,0x3f,sizeof ans);
    for(R ll i=1,x;i<=16;i++){
        char c=getchar();
        while(c!=0&&c!=1) c=getchar();
        x=c-0;
        if(x) goal+=1<<i-1;
    }
    ans[n]=0;
    Bfs(n);
}
inline ll read(){
    ll x=0,t=1;char ch=getchar();
    while(ch<0||ch>9){
        if(ch==-) t=-1;
        ch=getchar();
    }
    while(ch>=0&&ch<=9){
        x=x*10+ch-0;
        ch=getchar();
    }
    return x*t;
}
inline void write(ll x){
    if(x<0){putchar(-);x=-x;}
    if(x<=9){putchar(x+0);return;}
    write(x/10);putchar(x%10+0);
}
inline void writesp(ll x){
    write(x);putchar( );
}
inline void writeln(ll x){
    write(x);putchar(
);
}

 

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

bzoj1054[HAOI2008]移动玩具

P4289 [HAOI2008]移动玩具

[HAOI2008] 移动玩具 - BFS

Luogu-P4289-[HAOI2008]移动玩具

P4289 [HAOI2008]移动玩具

[HAOI2008]移动玩具