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 }

 

你可能感兴趣的:(HDU)