HDU-1430 魔板

来源:互联网 发布:sqlite for mac 编辑:程序博客网 时间:2024/06/05 19:58

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=1430

题意:

给出一个2*4的魔板上面有1-8八个数字蛇形排列,可以有三种操作,A:上下两行互换,B:整体循环右移一个,C:中间四个顺时针旋转一下。

求给出的两个状态之间转换的最小字典序的解。

思路:

类似于八数码,八数码看这里:http://blog.csdn.net/kopyh/article/details/48442415

但这道题的给定终点不一定又要字典序排列所以就类似于HDU-3567的八数码,因为这道题没有未知点X所以更好写一些,主体就是八数码的单向广搜打表+康托展开hash判重。

但是这题的精妙在于状态的映射,使得无论什么起始状态都可以映射到“12345678”这种状态到某种状态。

具体方法就是求出每组数据中每个数字要去的位置:

for(i=0;i<8;i++)pre[s[i]-'1']=i;for(i=0;i<8;i++)ss[i]=pre[ss[i]-'1']+'1';
想到这个就很容易了,确实巧妙。注意这题的特判,两个串相同时输出空行。

代码:

#define N 51234int vis[N],ans[N],cnt;char s[10],ss[10];struct node{    char str[10];    int pos;}tn;struct res{    int now,fa;}res[N];int  fac[] = {1,1,2,6,24,120,720,5040,40320};int KT(char s[]){    int i, j, t, sum;    sum = 0;    for (i=0; i<8; i++)    {        t = 0;        for (j=i+1; j<8; j++)            if (s[j] < s[i])                t++;        sum += t*fac[8-i-1];    }    return sum+1;}void changeA(char st[]){    for(int i=0;i<4;i++){char c=st[i];st[i]=st[7-i];st[7-i]=c;}}void changeB(char st[]){    char c=st[3];st[3]=st[2];st[2]=st[1];st[1]=st[0];st[0]=c;    c=st[4];st[4]=st[5];st[5]=st[6];st[6]=st[7];st[7]=c;}void changeC(char st[]){    char c=st[1];st[1]=st[6];st[6]=st[5];st[5]=st[2];st[2]=c;}void bfs(){    node g,h;    int t;    for(int i=0;i<8;i++)g.str[i]=i+'1';    g.pos=0; cnt=1;    memset(vis,-1,sizeof(vis));    res[0].now=-1;vis[0]=0;    queue<node> q;    while(!q.empty())q.pop();    q.push(g);    while(!q.empty())    {        g=q.front();q.pop();        h=g;        changeA(h.str);        t=KT(h.str);        if(vis[t]==-1)        {            vis[t]=cnt;h.pos=cnt;            res[cnt].now=1;res[cnt].fa=g.pos;            q.push(h);            cnt++;        }        h=g;        changeB(h.str);        t=KT(h.str);        if(vis[t]==-1)        {            vis[t]=cnt;h.pos=cnt;            res[cnt].now=2;res[cnt].fa=g.pos;            q.push(h);            cnt++;        }        h=g;        changeC(h.str);        t=KT(h.str);        if(vis[t]==-1)        {            vis[t]=cnt;h.pos=cnt;            res[cnt].now=3;res[cnt].fa=g.pos;            q.push(h);            cnt++;        }    }}int main(){    int i,j,k,kk,t,x,y,z;    int pre[10];    bfs();    while(scanf("%s",s)!=EOF)    {        scanf("%s",ss);        if(strcmp(s,ss)==0)        {            puts("");            continue;        }        for(i=0;i<8;i++)pre[s[i]-'1']=i;        for(i=0;i<8;i++)ss[i]=pre[ss[i]-'1']+'1';        t = vis[KT(ss)];        i=0;        while(res[t].now!=-1)        {            ans[i++]=res[t].now-1;            t = res[t].fa;        }        for(j=i-1;j>=0;j--)            printf("%c",'A'+ans[j]);        printf("\n");    }    return 0;}





0 0