1. 程式人生 > >FZU 2180 騎士 (雙向BFS)

FZU 2180 騎士 (雙向BFS)

#include<stdio.h>
#include<string.h>
#include<map>
#include<queue>
#include<algorithm>
#define inf 1e8
using namespace std;
char a[10][10]={"11111","01111","00*11","00001","00000"};
char b[10][10];
int state1,pos1,state2,pos2;
struct node
{
    int state;///圖中“1”分佈的狀態
    int pos;///“*”的位置編號
    int dis;///步數
};
int id[10][10];///記錄個點編號
const int f[8][2]={1,-2,1,2,2,1,2,-1,-1,2,-1,-2,-2,1,-2,-1};
int bfs()
{
    queue<node> q1,q2;
    map<pair<int,int>,int> m1,m2;///map對映的是步數
    pair<int,int> p1,p2;
    node now1,next1;
    node now2,next2;
    ///正向
    now1.state=state1;
    now1.pos=pos1;
    now1.dis=1;
    q1.push(now1);
    p1=make_pair(state1,pos1);
    m1[p1]=1;
    ///逆向
    now2.state=state2;
    now2.pos=pos2;
    now2.dis=1;
    q2.push(now2);
    p2=make_pair(state2,pos2);
    m2[p2]=1;

    if(state1==state2&&pos1==pos2) return 0;///一開始就是答案,輸出0

    while(q1.size()&&q2.size())
    {
        ///正向
        now1=q1.front();
        q1.pop();
        if(now1.dis>=9) return -1;
        int x,y;///將pos還原成座標
        x=now1.pos/5;
        y=now1.pos%5;
        for(int i=0;i<8;i++)
        {
            int mx=x+f[i][0];
            int my=y+f[i][1];
            if(mx<0||mx>=5||my<0||my>=5) continue;
            ///接下來將‘*’與(mx,my)處的值交換
            next1.pos=id[mx][my];
            next1.dis=now1.dis+1;
            next1.state=now1.state;///暫且存下來等待交換
            if(now1.state&(1<<id[mx][my]))///該位置為1(為0就不管state,因為不會改變圖中“1”的分佈情況)
            {
                next1.state|=(1<<id[x][y]);///將1交換到(x,y)處
                next1.state^=(1<<id[mx][my]);///由於(mx,my)處被換成了‘*’,所以該地方的1要清掉
            }
            p1=make_pair(next1.state,next1.pos);
            if(m1.find(p1)==m1.end())///用find高效很多,如果該處寫成if(!m1[p1]) 會慢很多,因為map非法查詢會多記憶體,會變很慢

            {
                if(m2.find(p1)!=m2.end()) return next1.dis+m2[p1]-2;
                m1[p1]=next1.dis;
                q1.push(next1);
            }
        }
        ///逆向
        now2=q2.front();
        q2.pop();
        if(now2.dis>=8) return -1;
        x=now2.pos/5;
        y=now2.pos%5;
        for(int i=0;i<8;i++)
        {
            int mx=x+f[i][0];
            int my=y+f[i][1];
            if(mx<0||mx>=5||my<0||my>=5) continue;
            next2.pos=id[mx][my];
            next2.dis=now2.dis+1;
            next2.state=now2.state;
            if(now2.state&(1<<id[mx][my]))
            {
                next2.state|=(1<<id[x][y]);
                next2.state^=(1<<id[mx][my]);
            }
            p2=make_pair(next2.state,next2.pos);
            if(m2.find(p2)==m2.end())
            {
                if(m1.find(p2)!=m1.end()) return next2.dis+m1[p2]-2;
                m2[p2]=next2.dis;
                q2.push(next2);
            }
        }
    }
    return -1;
}
void init()
{
    int num=0;
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
        id[i][j]=num++;
    state1=0;
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
    {
        if(a[i][j]=='1') state1|=(1<<id[i][j]);
        if(a[i][j]=='*') pos1=id[i][j];
    }
}
int main()
{
    init();///初始的圖是不會變的,預先處理就行
    int T;
    scanf("%d",&T);
    while(T--)
    {
        state2=0;
        for(int i=0;i<5;i++)
        {
            scanf("%s",b[i]);
            for(int j=0;j<5;j++)
            {
                if(b[i][j]=='1') state2|=(1<<id[i][j]);
                if(b[i][j]=='*') pos2=id[i][j];
            }
        }
        int res=bfs();
        if(res==-1||res>15) puts("Bored!");
        else printf("%d\n",res);
    }
    return 0;
}