bzoj 1054: [HAOI2008]移动玩具

状压bfs

一共有16个位置,最多会有 \(2^{16}=65536\) 种情况,用数组完全开的下。
用二进制中的1表示该位置有玩具,0表示该位置没有玩具。
由于广搜最先搜到的是最优解,直接用数组记录是否到达过该状态,顺便记录ans.
移动前的状态ans为0.
然后大力讨论12种情况即可
时间复杂度O( \(2^{16}\) )O(能过)
献上我又臭又长的代码


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
int z[524289],pan[524289];
int a,b,d;
char c;
queue<int>q;
int ex(int s,int li,int ri)
{
    return (s^(1<<li))^(1<<ri);
}
void fang(int xx,int fa)
{
    if(pan[xx]==0)
    {
        pan[xx]=1;
        z[xx]=z[fa]+1;
        q.push(xx);
    }
}
int main()
{
    //freopen("toy.in","r",stdin);
    //freopen("toy.out","w",stdout);
    for(int i=1;i<=16;++i)
    {
        cin>>c;
        a=(a<<1)|(c-'0');
    }
    for(int i=1;i<=16;++i)
    {
        cin>>c;
        b=(b<<1)|(c-'0');
    }
    if(a==b)
    {
        cout<<"0";
        return 0;
    }
    pan[a]=1;
    q.push(a);
    while(!q.empty())
    {
        int x=0;
        d=q.front();
        q.pop();
        if(d&(1<<15))//1号位 
        {
            if((d&(1<<14))==0)
            {
                x=ex(d,15,14);
                fang(x,d);
            }
            if((d&(1<<11))==0)
            {
                x=ex(d,15,11);
                fang(x,d);
            }
        }
        for(int i=2;i<=3;++i)//2~3号位 
        {
            if(d&(1<<(16-i)))
            {
                if((d&(1<<(16-i+1)))==0)
                {
                    x=ex(d,16-i,16-i+1);
                    fang(x,d);
                }
                if((d&(1<<(16-i-1)))==0)
                {
                    x=ex(d,16-i,16-i-1);
                    fang(x,d);
                }
                if((d&(1<<(16-i-4)))==0)
                {
                    x=ex(d,16-i,16-i-4);
                    fang(x,d);
                }
            }
        }
        if(d&(1<<12))//4号位 
        {
            if((d&(1<<13))==0)
            {
                x=ex(d,13,12);
                fang(x,d);
            }
            if((d&(1<<8))==0)
            {
                x=ex(d,12,8);
                fang(x,d);
            }
        }
        if(d&(1<<11))//5号位 
        {
            if((d&(1<<15))==0)
            {
                x=ex(d,15,11);
                fang(x,d);
            }
            if((d&(1<<10))==0)
            {
                x=ex(d,10,11);
                fang(x,d);
            }
            if((d&(1<<7))==0)
            {
                x=ex(d,7,11);
                fang(x,d);
            }
        }
        for(int i=6;i<=7;++i)//6~7号位 
        {
            if(d&(1<<(16-i)))
            {
                if((d&(1<<(16-i+4)))==0)
                {
                    x=ex(d,16-i,16-i+4);
                    fang(x,d);
                }
                if((d&(1<<(16-i+1)))==0)
                {
                    x=ex(d,16-i,16-i+1);
                    fang(x,d);
                }
                if((d&(1<<(16-i-1)))==0)
                {
                    x=ex(d,16-i,16-i-1);
                    fang(x,d);
                }
                if((d&(1<<(16-i-4)))==0)
                {
                    x=ex(d,16-i,16-i-4);
                    fang(x,d);
                }
            }
        }
        if(d&(1<<8))//8号位 
        {
            if((d&(1<<12))==0)
            {
                x=ex(d,8,12);
                fang(x,d);
            }
            if((d&(1<<9))==0)
            {
                x=ex(d,8,9);
                fang(x,d);
            }
            if((d&(1<<4))==0)
            {
                x=ex(d,8,4);
                fang(x,d);
            }
        }
        if(d&(1<<7))//9号位 
        {
            if((d&(1<<11))==0)
            {
                x=ex(d,7,11);
                fang(x,d);
            }
            if((d&(1<<6))==0)
            {
                x=ex(d,7,6);
                fang(x,d);
            }
            if((d&(1<<3))==0)
            {
                x=ex(d,7,3);
                fang(x,d);
            }
        }
        for(int i=10;i<=11;++i)//10~11号位 
        {
            if(d&(1<<(16-i)))
            {
                if((d&(1<<(16-i+4)))==0)
                {
                    x=ex(d,16-i,16-i+4);
                    fang(x,d);
                }
                if((d&(1<<(16-i+1)))==0)
                {
                    x=ex(d,16-i,16-i+1);
                    fang(x,d);
                }
                if((d&(1<<(16-i-1)))==0)
                {
                    x=ex(d,16-i,16-i-1);
                    fang(x,d);
                }
                if((d&(1<<(16-i-4)))==0)
                {
                    x=ex(d,16-i,16-i-4);
                    fang(x,d);
                }
            }
        }
        if(d&(1<<4))//12号位 
        {
            if((d&(1<<8))==0)
            {
                x=ex(d,8,4);
                fang(x,d);
            }
            if((d&(1<<5))==0)
            {
                x=ex(d,4,5);
                fang(x,d);
            }
            if((d&(1<<0))==0)
            {
                x=ex(d,4,0);
                fang(x,d);
            }
        }
        if(d&(1<<3))//13号位 
        {
            if((d&(1<<7))==0)
            {
                x=ex(d,3,7);
                fang(x,d);
            }
            if((d&(1<<2))==0)
            {
                x=ex(d,3,2);
                fang(x,d);
            }
        }
        for(int i=14;i<=15;++i)//14~15号位 
        {
            if(d&(1<<(16-i)))
            {
                if((d&(1<<(16-i+4)))==0)
                {
                    x=ex(d,16-i,16-i+4);
                    fang(x,d);
                }
                if((d&(1<<(16-i+1)))==0)
                {
                    x=ex(d,16-i,16-i+1);
                    fang(x,d);
                }
                if((d&(1<<(16-i-1)))==0)
                {
                    x=ex(d,16-i,16-i-1);
                    fang(x,d);
                }
            }
        }
        if(d&(1<<0))//16号位 
        {
            if((d&(1<<1))==0)
            {
                x=ex(d,0,1);
                fang(x,d);
            }
            if((d&(1<<4))==0)
            {
                x=ex(d,4,0);
                fang(x,d);
            }
        }
    }
    cout<<z[b];
    fclose(stdin);fclose(stdout);
    return 0;
}
posted @ 2019-09-07 19:43  wljss  阅读(120)  评论(0编辑  收藏  举报