POJ1184-------操作分离的BFS

题目地址:http://poj.org/problem?id=1184

题目意思:

给你两个6位数,一个是起始值,一个最终值

初始光标在最左边

你可以左移或者右移光变

在光标处+1或者-1

在光标处和最左边或者和最右边交换

问你最少要多少就可以由初始值转换到最终值

解题思路:

操作分离是解决这题的核心思想

就是说我们反正要进行一些转换的,不如先全部转换了算了

通过一个BFS预处理将所有可能转换的全部转换,光标所有可能的位置全部求出来

然后在每次要求的时候,对每种状态上的光标进行加减操作

求出最少的步骤

另外这题的测试数据有问题,其实左移也是需要的

比如000159 和 000519,正确答案是8,如果不考虑左移就是12

再就是我们可以将光标的访问情况压缩到10种,具体的在我代码中有解释

下面上代码:

 

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cmath>

#include<string>

#include<map>

#include<queue>

using namespace std;



struct node

{

    int state;

    int pos;

    int num[6];

    int step;

    int fangwen[6];

};



int vis_state[10][6] =

{

    1,0,0,0,0,0,  /*访问状态0: 初始状态(pos=0)*/

    1,1,0,0,0,0,  /*访问状态1: 状态0通过右移操作得到(pos=1),或者状态1通过swap0操作得到(pos=1)*/

    1,1,1,0,0,0,  /*访问状态2: 状态1通过右移操作得到(pos=2),或者状态2通过swap0操作得到(pos=2)*/

    1,1,1,1,0,0,  /*访问状态3: 状态2通过右移操作得到(pos=3),或者状态3通过swap0操作得到(pos=3)*/

    1,1,1,1,1,0,  /*访问状态4: 状态3通过右移操作得到(pos=4),或者状态4通过swap0操作得到(pos=4)*/

    1,0,0,0,0,1,  /*访问状态5: 状态0通过swap1操作得到(pos=0),或者状态5通过swap0操作得到(pos=0)*/

    1,1,0,0,0,1,  /*访问状态6: 状态1通过swap1操作得到(pos=1),或者状态5通过右移操作得到(pos=1),或者状态6通过swap0操作得到(pos=1)*/

    1,1,1,0,0,1,  /*访问状态7: 状态2通过swap1操作得到(pos=2),或者状态6通过右移操作得到(pos=2),或者状态7通过swap0操作得到(pos=2)*/

    1,1,1,1,0,1,  /*访问状态8: 状态3通过swap1操作得到(pos=3),或者状态7通过右移操作得到(pos=3),或者状态8通过swap0操作得到(pos=3)*/

    1,1,1,1,1,1   /*访问状态9: 状态4通过swap1操作得到(pos=4),或者状态8通过右移操作得到(pos=4),或者状态9通过右移操作得到(pos=5),

                               或者状态4通过右移操作得到(pos=5),或者状态9通过swap0操作得到,或者状态9通过swap1操作得到*/

};



int state[10000][8]; //对应的是所有情况,第二维记录相应信息



int idx;

int co;



bool vis[6][6][6][6][6][6][6][10];  //前6个是数字,为什么只到6,是因为这个是做排列用的

                                    //第7个是光标所在位置用的,第8个事state



void put_to_vis(node a)

{

    vis[a.num[0]][a.num[1]][a.num[2]][a.num[3]][a.num[4]][a.num[5]][a.pos][a.state] = true;

}



bool check(node a)

{

    return vis[a.num[0]][a.num[1]][a.num[2]][a.num[3]][a.num[4]][a.num[5]][a.pos][a.state];

}



int find_state(node a)

{

    if(a.fangwen[5]==0)

    {

        int cnt = 0;

        for(int i=1;i<5;i++)

            if(a.fangwen[i])

                cnt++;

        return cnt;

    }

    else

    {

        int cnt = 0;

        for(int i=1;i<5;i++)

            if(a.fangwen[i])

                cnt++;

        return cnt+5;

    }

}







void bfs()

{

    queue<node> Q;

    node a,b;

    idx=0;

    co=0;

    for(int i=0;i<6;i++)

    {

        a.num[i] = i;

        a.fangwen[i] = 0;

    }



    a.pos = a.state = a.step = 0;

    a.fangwen[0] = 1;

    Q.push(a);

    put_to_vis(a);



    //printf("a step %d\n",a.step);

    int co2=0;



    while(!Q.empty())

    {

        co++;

        a = Q.front();

        Q.pop();



        for(int i=0;i<6;i++)

            state[idx][i] = a.num[i];

        state[idx][6] = a.state;

        state[idx][7] = a.step;

        idx++;



        if(a.pos>0) //左移或者左交换操作

        {

            //左移操作

            b=a;

            b.step = a.step+1;

            b.pos--;

            if(!check(b))

            {

                put_to_vis(b);

                Q.push(b);

            }



            //左交换

            b = a;

            b.step = a.step+1;

            swap(b.num[0],b.num[b.pos]);

            if(!check(b))

            {

                put_to_vis(b);

                Q.push(b);

            }

        }



        if(a.pos<5) //右移和右交换操作

        {

            //右移

            b=a;

            b.step = a.step+1;

            b.pos++;

            b.fangwen[b.pos] = 1;

            b.state = find_state(b);

            if(!check(b))

            {

                put_to_vis(b);

                Q.push(b);

            }



            //右交换

            b = a ;

            b.step = a.step+1;

            swap(b.num[5],b.num[b.pos]);

            b.fangwen[5] = 1;

            b.state = find_state(b);

            if(!check(b))

            {

                put_to_vis(b);

                Q.push(b);

            }

        }

    }

}



int main()

{

    memset(vis,false,sizeof(vis));

    bfs();

    char st[10];

    char ed[10];

    int _st[6];

    int _ed[6];

    while(scanf("%s%s",st,ed) != EOF)

    {

        for(int i=0;i<6;i++)

        {

            _st[i] = st[i]-'0';

            _ed[i] = ed[i]-'0';

        }





        int ans = 99999999;



        for(int i=0;i<idx;i++)

        {

            int tmp = state[i][7];//初始化为进行了交换后的步数

            bool flag = true;

            int j;

            for(j=0;j<6;j++)

            {

                if(!vis_state[state[i][6]][j] && (_st[state[i][j]]!=_ed[j])  )

                {

                    flag = false;

                    break;

                }

                else

                {

                    tmp += abs( _st[state[i][j]] - _ed[j]); //再加上每位进行加减 操作的步数

                }

            }



            if(flag)

                ans = min(ans,tmp);



        }

        printf("%d\n",ans);

    }

    return 0;

}






















 

 

你可能感兴趣的:(poj)