hdu1430魔板

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
12345678 17245368 12345678 82754631
 

 

Sample Output
C AC

由于刚做完八数码问题,再来做这题,认为非常简单。可是用bfs超时(原因是多组数据,太多的数据将程序拖到超时),用dbfs就一直wa(原来是反向的搜索不能保证后半段的字典序最小,只能保证后半段的逆序的字典序最小),所以就得不到正确结果。

百度了一下,原来使用映射+bfs预处理的方法解决的,这样,再多组数据也不怕了。

将任意的初始状态映射为12345678,在这个过程中得到一个映射函数,目标状态根据这个映射函数,映射为相应的目标状态。(这样子能得到正确答案的原因是,魔板的变换,其实只是位置的变换,数字只是用来标记位置的而已,通过同一种映射关系将初始和目标状态的标记同时该改变,所以仍然能得到正确答案)

那么所有的数据,都能转化为初始状态为12345678的搜索,那么只要一遍bfs搜索出12345678所有能到达的状态,并记录步骤即可。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <queue>
 4 #include <string>
 5 #include <iostream>
 6 using namespace std;
 7 char st[9],ed[9];
 8 int vis[55555];
 9 string ans[55555];
10 int fac[10] = {1,1,2,6,24,120,720,5040,40320};
11 int getHash(char *str)//康托展开
12 {
13     int i,j,hash = 0,cnt;
14     for(i=0; i<8; ++i)
15     {
16         cnt = 0;
17         for(j=i+1; j<8; ++j)
18             if(str[j]<str[i])
19                 cnt++;
20         hash += cnt * fac[8-i-1];
21     }
22     return hash;
23 }
24 struct node
25 {
26     char str[8];
27 };
28 int d[3][8] = {{7,6,5,4,3,2,1,0},{3,0,1,2,5,6,7,4},{0,6,1,3,4,2,5,7}};
29 char change[8];
30 
31 void bfs()
32 {
33     queue<node> q;
34     node cur,tmp;
35     int i,j;
36     for(i=0; i<8; ++i)
37         cur.str[i] = i + '1';
38     int hash = getHash(cur.str);
39     q.push(cur);
40     vis[hash] = true;
41     q.push(cur);
42     while(!q.empty())
43     {
44         cur = q.front(); q.pop();
45         int pHash = getHash(cur.str);
46         for(i=0; i<3; ++i)
47         {
48             for(j=0; j<8; ++j)
49                 tmp.str[j] = cur.str[d[i][j]];
50             hash = getHash(tmp.str);
51             if(vis[hash]) continue;
52             vis[hash] = true;
53             ans[hash] = ans[pHash] + (char)('A' + i);
54             q.push(tmp);
55         }
56     }
57 }
58 
59 
60 int main()
61 {
62     bfs();
63     int i;
64     while(scanf("%s%s",st,ed)!=EOF)
65     {
66         for(i=0; i<8; ++i)
67             change[st[i]-'1'] =  i+'1';//得到映射函数
68         for(i=0; i<8; ++i)
69             ed[i] = change[ed[i]-'1'];//根据映射函数改变目标状态
70         int hash = getHash(ed);
71         cout<<ans[hash]<<endl;
72     }
73     return 0;
74 }

 

posted @ 2015-02-01 10:39  justPassBy  阅读(694)  评论(0编辑  收藏  举报