hdu1430 魔板(双向bfs+输出路径+字典序最小)

来源:互联网 发布:日语翻译软件哪个好 编辑:程序博客网 时间:2024/04/29 20:40



魔板

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1352    Accepted Submission(s): 270


Problem Description
在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板。魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示。任一时刻魔板的状态可用方块的颜色序列表示:从魔板的左上角开始,按顺时针方向依次写下各方块的颜色代号,所得到的数字序列即可表示此时魔板的状态。例如,序列(1,2,3,4,5,6,7,8)表示魔板状态为:

1 2 3 4
8 7 6 5

对于魔板,可施加三种不同的操作,具体操作方法如下:

A: 上下两行互换,如上图可变换为状态87654321
B: 每行同时循环右移一格,如上图可变换为41236785
C: 中间4个方块顺时针旋转一格,如上图可变换为17245368

给你魔板的初始状态与目标状态,请给出由初态到目态变换数最少的变换步骤,若有多种变换方案则取字典序最小的那种。
 

Input
每组测试数据包括两行,分别代表魔板的初态与目态。
 

Output
对每组测试数据输出满足题意的变换步骤。
 

Sample Input
12345678172453681234567882754631
 

Sample Output
CAC
 

Author
LL
 

Source
ACM暑期集训队练习赛(三)
 

Recommend
linle
 
题目大意:中文题不解释。

题目分析:这题类似八数码,看完题分析了一下,8个位置每个位置9个状态,由于数字都不一样,判重用康托展开。

所以一共只有8!种状态,所以先拍了一个朴素的bfs,

结果华丽丽的TLE了,因为后台的case太多了。。单向不行那就双向吧。正好也练习一下双向bfs,

虽然这题只需要单向bfs预处理就可以很快过,但只是为了练习一下,

结果就走上了WA的不归路啊啊啊,整整跪了2天。最后感谢@FancyMouse    的帮助,找到了bug,终于过了啊啊啊啊。

这题双向bfs本来没那么复杂,不过要输出路径就有点复杂了,更dt的是还要字典序最小!!

方法是这样的,正向搜索很常规,直接搜就行了,按ABC依次扩展。flag[0][state]记录的是正向搜索从起点的

一条路径中state状态的前驱,那么op[0][state]记录的就是从state状态的前驱到state状态所用的操作。

反向也差不多,从终点依次向中间扩展,不过扩展的时候不是做相应的ABC操作,而是做ABC3种操作的逆操作,

即:A操作还是将字符串翻转,B操作就是每行左移1格了,C操作是中间4个左旋1格,这样有什么好处呢,

我们发现最后正反双向搜索搜到重复节点的时候要输出路径,这样的话我们直接从相遇点依次扫到终点,

扫出来的路径就是正向操作的路径。比如从终点逆向扩展2步CA到达某个倒数第二步,那么正着看,

从这个倒数第二步通过正常的AC操作也是能到达终点的。所以op[1][state]记录的就是从终点反向

扩展到state状态所用的逆操作,其实正着看就是从state状态往终点走的下一步的正向操作也是op[1][state]

flag[1][state]就是记录的state状态往终态走的后继状态,这样就能保证前后

2半都是字典序最小(想一想,为什么)。但是每找到一个解,不着急输出,不要着急跳出循环,

而是还要继续比较一下。我就是因为这一点长跪不起,

一直WA,因为搜索的过程中会有多解,比如这题的BCCC和ABCA就是效果相同的操作。

如果2个解是aaabbb和bbbaaa,并且在反向搜索的时候找到解,那么反向因为保证了字典序最小了,

所以反向会先扩展到aaa,找到解,如果直接

break显然有问题,

因为显然这个字典序不一定是最小的,显然没有考虑到前半段的结果。所以我们

找到解后不着急跳出来,只要标记上就可以了,把同一层的搜完,选出字典序最小的作为最优解。

代码写的比较臭比较长,但是比较清晰。

详情请见代码:

#include <iostream>#include<cstdio>#include<queue>#include<cstring>using namespace std;const int N = 1000005;int flag[2][50000];char op[2][50000];long fac[] = {1,1,2,6,24,120,720,5040,40320,362880};struct node{    int step,val;    char state[10];}ss,now,temp[N];int tmpnum;struct que{    struct node t[N];    int head,tail;    void init()    {        head = tail = 0;    }    bool empty()    {        return tail == head;    }    struct node top()    {        return t[head];    }    void push(struct node a)    {        t[tail] = a;        tail ++;        if(tail >= N)            tail %= N;    }    void pop()    {        head ++;        if(head >= N)            head %= N;    }}q[2];//queue<node>q[2];int contor(){    int i,j;    long temp,num;    num = 0;    for(i = 0;i < 8;i ++)    {        temp = 0;        for(j = i + 1;j < 8;j ++)            if(ss.state[j] < ss.state[i])                temp ++;        num += temp * fac[8 - i - 1];    }    return num;}void change(int type){    int i;    char c;    switch(type)    {        case 1:for(i = 0;i < 4;i ++)                {                    ss.state[i] ^= ss.state[7 - i];                    ss.state[7 - i] ^= ss.state[i];                    ss.state[i] ^= ss.state[7 - i];                }               break;        case 2:c = ss.state[3];                for(i = 3;i > 0;i --)                    ss.state[i] = ss.state[i - 1];                ss.state[i] = c;                c = ss.state[4];                for(i = 4;i < 7;i ++)                    ss.state[i] = ss.state[i + 1];                ss.state[i] = c;                break;        case 3:c = ss.state[1];                ss.state[1] = ss.state[6];                ss.state[6] = ss.state[5];                ss.state[5] = ss.state[2];                ss.state[2] = c;                break;    }}void change2(int type){    int i;    char c;    switch(type)    {        case 1:for(i = 0;i < 4;i ++)                {                    ss.state[i] ^= ss.state[7 - i];                    ss.state[7 - i] ^= ss.state[i];                    ss.state[i] ^= ss.state[7 - i];                }               break;        case 2:c = ss.state[0];                for(i = 0;i < 3;i ++)                    ss.state[i] = ss.state[i + 1];                ss.state[i] = c;                c = ss.state[7];                for(i = 7;i > 4;i --)                    ss.state[i] = ss.state[i - 1];                ss.state[i] = c;                break;        case 3:c = ss.state[1];                ss.state[1] = ss.state[2];                ss.state[2] = ss.state[5];                ss.state[5] = ss.state[6];                ss.state[6] = c;                break;    }}char s1[10],s2[10];int end,start;char ans[50000];char tans[5000];char ttans[5000];int ansnum;void print(){    int i;    int root = ss.val;    int num = 0;tans[num ++] = op[0][ss.val];    while(root != start)    {        root = flag[0][root];tans[num ++] = op[0][root];    }int p = 0;    for(i = num - 2;i >= 0;i --){        //printf("%c",ans[i]);ttans[p ++] = tans[i];}    num = 0;    root = ss.val;tans[num ++] = op[1][ss.val];    while(root != end)    {root = flag[1][root];        tans[num ++] = op[1][root];    }    for(i = 0;i < num - 1;i ++){        //printf("%c",ans[i]);ttans[p ++] = tans[i];}ttans[p] = '\0';if(ansnum){if(strcmp(ans,ttans) > 0)strcpy(ans,ttans);}elsestrcpy(ans,ttans);ansnum ++;//newans;}int main(){    int i,j;    while(~scanf("%s%s",s1,s2))    {        if(strcmp(s1,s2) == 0)        {            puts("");            continue;        }        q[0].init();        q[1].init();//        while(!q[0].empty())//            q[0].pop();//        while(!q[1].empty())//            q[1].pop();        memset(flag,-1,sizeof(flag));        memset(op,0,sizeof(op));        ss.step = 0;        strcpy(ss.state,s1);        start = contor();        ss.val = start;        flag[0][start] = start;        q[0].push(ss);        strcpy(ss.state,s2);        end = contor();        ss.val = end;        flag[1][end] = end;        q[1].push(ss);        bool ok = false;        i = 0;tmpnum = 0;ansnum = 0;        while(!ok)        {            while(!q[0].empty() && q[0].top().step == i)            {                now = q[0].top();                q[0].pop();                ss = now;                ss.step ++;                change(1);                ss.val = contor();                if(flag[0][ss.val] == -1)                {                    flag[0][ss.val] = now.val;                    op[0][ss.val] = 'A';                    if(flag[1][ss.val] != -1)                    {                        print();                        ok = true;                        //break;//罪恶的break                    }                    q[0].push(ss);                }                ss = now;                ss.step ++;                change(2);                ss.val = contor();                if(flag[0][ss.val] == -1)                {                    flag[0][ss.val] = now.val;                    op[0][ss.val] = 'B';                    if(flag[1][ss.val] != -1)                    {                        print();                        ok = true;                        //break;//wa之源                    }                    q[0].push(ss);                }                ss = now;                ss.step ++;                change(3);                ss.val = contor();                if(flag[0][ss.val] == -1)                {                    flag[0][ss.val] = now.val;                    op[0][ss.val] = 'C';                    if(flag[1][ss.val] != -1)                    {                        print();                        ok = true;                        //break;//冷静分析                    }                    q[0].push(ss);                }            }if(ok)break;            while(!q[1].empty() && q[1].top().step == i)            {//先把同一层的一起出队,同时按ABC扩展,这样才能保证反向                temp[tmpnum ++] = q[1].top();//字典序最小,                q[1].pop();//如果不能理解,用笔在纸上画画就明白了            }            for(j = 0;j < tmpnum;j ++)            {                ss = temp[j];                ss.step ++;                change2(1);                ss.val = contor();                if(flag[1][ss.val] == -1)                {                    flag[1][ss.val] = temp[j].val;                    op[1][ss.val] = 'A';                    if(flag[0][ss.val] != -1)                    {                        print();                        ok = true;                       // break;//break要三思                    }                    q[1].push(ss);                }            }            for(j = 0;j < tmpnum;j ++)            {                ss = temp[j];                ss.step ++;                change2(2);                ss.val = contor();                if(flag[1][ss.val] == -1)                {                    flag[1][ss.val] = temp[j].val;                    op[1][ss.val] = 'B';                    if(flag[0][ss.val] != -1)                    {                        print();                        ok = true;                       // break;//早该想到的                    }                    q[1].push(ss);                }            }            for(j = 0;j < tmpnum;j ++)            {                ss = temp[j];                ss.step ++;                change2(3);                ss.val = contor();                if(flag[1][ss.val] == -1)                {                    flag[1][ss.val] = temp[j].val;                    op[1][ss.val] = 'C';                    if(flag[0][ss.val] != -1)                    {                        print();                        ok = true;                       // break;//。。。。                    }                    q[1].push(ss);                }            }            tmpnum = 0;            i ++;if(ok)break;        }        printf("%s\n",ans);    }    return 0;}//1234MS820K//625MS924K 好吧,g++提交时间快了一倍。。。/*12345678645728131234567874381652158746237384165212345678827546311234567848136275123456781234567812345678876543211234567841236785123456785876321412345678863542711234567858632714123456785186372412345678427368151763825446273185762538412638715413578642246875313671825482716435123456782134567846753812543876123752168454137628*/
CSDN的排版怎么回事啊啊啊。。。。
原创粉丝点击