poj 1184 广搜 状态压缩

题意:6个数字,每次可以左移/右移光标,或将光标所在数字加一/减一,或将光标所在数字与第一个/第六个数字交换,问达到目标数字,最少需要多少次操作?

分析:操作可以分成两部分考虑:移动光标和交换改变了原数字的位置,而加一减一改变数字的大小。

先bfs出012345所能达到的所有状态,以及达到此状态光标经过了哪些数字。再针对新状态和目标状态,如果某一位数字不一样并且光标经过这一位,则可以改变此数字的大小,若没经过,则此状态无法达到目标状态。表达起来太费劲了,直接看代码吧。

另外,据说左移操作是多余的,把代码中左移部分去掉,也AC了,但还是感觉有问题。。  有空再想吧。。

 

 

const int M = 567;
struct node{
    int a[6], step, pos, sta;//数字的排列 步数 光标位置 光标经过的状态
}d[M];
int h, r;//队列首尾指针

bool sta[10][6] = { {1,0,0,0,0,0},  //1表示该位可改变
                    {1,1,0,0,0,0},
                    {1,1,1,0,0,0},
                    {1,1,1,1,0,0},
                    {1,1,1,1,1,0},
                    {1,1,1,1,1,1},
                    {1,0,0,0,0,1},
                    {1,1,0,0,0,1},
                    {1,1,1,0,0,1},
                    {1,1,1,1,0,1},
                };
bool b[6][6][6][6][6][6][6][10];//判重
#define vis b[d[h].a[0]][d[h].a[1]][d[h].a[2]][d[h].a[3]][d[h].a[4]][d[h].a[5]][d[h].pos][d[h].sta]

void bfs(){
    FOR(i, 0, 6) d[h].a[i] = i; d[h].step = 0; d[h].pos = 0; d[h].sta = 0; vis = 1; h++;
    while(r<h){
        if(d[r].pos<5){
            //光标右移
            d[h].step=d[r].step+1; d[h].pos=d[r].pos+1;

            if(sta[d[r].sta][d[r].pos+1]) d[h].sta=d[r].sta;
            else if(d[r].sta==9) d[h].sta=5;
            else d[h].sta=d[r].sta+1;

            FOR(i, 0, 6) d[h].a[i]=d[r].a[i];
            if(vis==0) { vis=1; h++;}

            //和6交换
            d[h].step=d[r].step+1; d[h].pos=d[r].pos;

            if(d[r].sta<4) d[h].sta=d[r].sta+6;
            else if(d[r].sta==4) d[h].sta=5;
            else d[h].sta=d[r].sta;

            FOR(i, 0, 6) d[h].a[i]=d[r].a[i];
            swap(d[h].a[d[h].pos], d[h].a[5]);

            if(vis==0) { vis=1; h++;}
        }
        if(d[r].pos>0){
            //光标左移
            /*d[h].step=d[r].step+1; d[h].pos=d[r].pos-1; d[h].sta=d[r].sta;
            FOR(i, 0, 6) d[h].a[i]=d[r].a[i];
            if(vis==0) { vis=1; h++;}
            */
            //和1交换
            d[h].step=d[r].step+1; d[h].pos=d[r].pos; d[h].sta=d[r].sta;

            FOR(i, 0, 6) d[h].a[i]=d[r].a[i];
            swap(d[h].a[d[h].pos], d[h].a[0]);

            if(vis==0) { vis=1; h++;}
        }
        r++;
    }
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    #endif

    bfs();

    string s1,s2;
    cin>>s1>>s2;
    int x[6], y[6];
    FOR(i, 0, 6) x[i]=s1[i]-'0', y[i]=s2[i]-'0';

    int ans=-1;
    FOR(p, 0, h){           //cout<<h<<endl;
        int flag=0, cnt=d[p].step, s=d[p].sta;
        FOR(i, 0, 6)
            if( x[ d[p].a[i] ] != y[i] ) {
                if( sta[s][i] == 0 ) {flag=1; break;}
                else cnt += abs( x[ d[p].a[i] ]-y[i] );
            }
        if(flag) continue;
        checkmin(ans, cnt);
    }

    cout<<ans<<endl;

    return 0;
}

 

posted @ 2013-05-26 20:46  心向往之  阅读(402)  评论(0编辑  收藏  举报