1. 程式人生 > >[BZOJ1054/Luogu4289][HAOI2008]移動玩具

[BZOJ1054/Luogu4289][HAOI2008]移動玩具

題目連結:

BZOJ1054

Luogu4289

日常水題

因為總共\(16\)個節點,用二進位制表示每一個狀態,跑一遍最短路即可。

因為邊權都是\(1\),直接\(BFS\)即可。

時間複雜度 \(O(2^{16}*16*4)=AC\)

#include <queue>
#include <cstdio>
#include <cstring>

int St,Ed,Dis[1<<16];
char s[5];

void BFS()
{
    if(St==Ed)return;
    std::queue<int> q;
    memset(Dis,0x3f,sizeof Dis);
    q.push(St),Dis[St]=0;
    for(int x;!q.empty();)
    {
        x=q.front(),q.pop();
        for(int i=0;i<16;++i)
        {
            int wx;
            if(i<12&&(x>>i&1)!=(x>>(i+4)&1))//不是第一行,且狀態與上方不同
            {
                wx=x^(1<<i)^(1<<(i+4));//交換兩位
                if(Dis[wx]>Dis[x]+1)
                {
                    Dis[wx]=Dis[x]+1;
                    if(wx==Ed)return;
                    q.push(wx);
                }
            }//向上
            if(i>3&&(x>>i&1)!=(x>>(i-4)&1))
            {
                wx=x^(1<<i)^(1<<(i-4));
                if(Dis[wx]>Dis[x]+1)
                {
                    Dis[wx]=Dis[x]+1;
                    if(wx==Ed)return;
                    q.push(wx);
                }
            }//向下
            if(i%4!=3&&(x>>i&1)!=(x>>(i+1)&1))
            {
                wx=x^(1<<i)^(1<<(i+1));
                if(Dis[wx]>Dis[x]+1)
                {
                    Dis[wx]=Dis[x]+1;
                    if(wx==Ed)return;
                    q.push(wx);
                }
            }//向左
            if(i%4&&(x>>i&1)!=(x>>(i-1)&1))
            {
                wx=x^(1<<i)^(1<<(i-1));
                if(Dis[wx]>Dis[x]+1)
                {
                    Dis[wx]=Dis[x]+1;
                    if(wx==Ed)return;
                    q.push(wx);
                }
            }//向右
        }
    }
}

int main()
{
    for(int i=0;i<4;++i)
    {
        scanf("%s",s);
        for(int j=0;j<4;++j)
            St=St<<1|(s[j]&1);
    }
    for(int i=0;i<4;++i)
    {
        scanf("%s",s);
        for(int j=0;j<4;++j)
            Ed=Ed<<1|(s[j]&1);
    }
    BFS();
    printf("%d\n",Dis[Ed]);
    return 0;
}