ACM/ICPC 之 BFS(离线)+康拓展开(TSH OJ-玩具(Toy))

祝大家新年快乐,相信在新的一年里一定有我们自己的梦!

这是一个简化的魔板问题,只需输出步骤即可。

玩具(Toy)


描述

ZC神最擅长逻辑推理,一日,他给大家讲述起自己儿时的数字玩具。

该玩具酷似魔方,又不是魔方。具体来说,它不是一个3 * 3 * 3的结构,而是4 * 2的结构。

按照该玩具约定的玩法,我们可反复地以如下三种方式对其做变换:

A. 交换上下两行。比如,图(a)经此变换后结果如图(b)所示。

B. 循环右移(ZC神从小就懂得这是什么意思的)。比如,图(b)经此变换后结果如图(c)所示。

C. 中心顺时针旋转。比如,图(c)经此变换后结果如图(d)所示。

ZC神自小就是这方面的天才,他往往是一只手还没揩干鼻涕,另一只手已经迅速地将处于任意状态的玩具复原至如图(a)所示的初始状态。物质极其匮乏的当年,ZC神只有一个这样的玩具;物质极大丰富的今天,你已拥有多个处于不同状态的玩具。现在,就请将它们全部复原吧。

输入

第一行是一个正整数,即你拥有的魔方玩具总数N。

接下来共N行,每行8个正整数,表示该玩具的当前状态。

这里,魔方状态的表示规则为:前四个数自左向右给出魔方的第一行,后四个数自右向左给出第二行。比如,初始状态表示为“1 2 3 4 5 6 7 8”。

输出

共N行,各含一个整数,依次对应于复原各玩具所需执行变换的最少次数。

特别地,若某个玩具不可复原,则相应行输出-1。

输入样例

2
1 2 3 4 5 6 7 8
8 6 3 5 4 2 7 1

输出样例

0
2

限制

对于60%的数据,N = 1

对于100%的数据,1 <= N <= 1,000

时间:1 sec

空间:20MB

提示

状态转换图及其搜索


  解法可以参看我的另一篇文章:ACM/ICPC 之 BFS(离线)+康拓展开 (HDU1430-魔板)

  具体代码如下:

 1 //玩具(Toy),类似魔板问题,但只需输出步骤数即可
 2 //Time:28Ms  Memory:13376MB (No.10)
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 using namespace std;
 7 #define MAX 40321
 8 int Map[MAX];    //状态图
 9 int fac[8] = { 1,1,2,6,24,120,720,5040};
10 struct Board{
11     int fa;        //记录上一状态
12     int val;    //Hash值
13     char str[9];
14     void Contor();
15 }m[2*MAX],ts;
16 void Board::Contor()
17 {
18     int num = 0;
19     for (int i = 0; i < 8; i++)
20     {
21         int tmp = 0;
22         for (int j = i + 1; j < 8; j++)
23         {
24             if (this->str[j] < this->str[i]) tmp++;
25         }
26         num += tmp*fac[7 - i];
27     }
28     this->val = num;
29 }
30 void Init(char s[9])
31 {
32     int rear = 0;
33     int tail = 1;
34     strcpy(m[0].str, s);
35     m[0].Contor();
36     while (rear < tail) {
37         if (Map[m[rear].val])
38         {
39             rear++;
40             continue;
41         }
42         Map[m[rear].val] = Map[m[m[rear].fa].val] + 1;
43         /*由于是反向搜索,因此将逆向操作即可*/
44         // 交换行
45         for (int i = 0; i < 8; i++)
46             m[tail].str[(i + 4) % 8] = m[rear].str[i];
47         m[tail].Contor();
48         if (!Map[m[tail].val]) {
49             m[tail].fa = rear;
50             tail++;
51         }
52         // 循环左移
53         for (int i = 0; i < 4; i++)
54             m[tail].str[(i + 3) % 4] = m[rear].str[i];
55         for (int i = 4; i < 8; i++)
56             m[tail].str[(i + 3) % 4 + 4] = m[rear].str[i];
57         m[tail].Contor();
58         if (!Map[m[tail].val]) {
59             m[tail].fa = rear;
60             tail++;
61         }
62         // 中心逆旋转
63         strcpy(m[tail].str, m[rear].str);
64         m[tail].str[5] = m[rear].str[1]; m[tail].str[1] = m[rear].str[2];
65         m[tail].str[2] = m[rear].str[6]; m[tail].str[6] = m[rear].str[5];
66         m[tail].Contor();
67         if (!Map[m[tail].val]) {
68             m[tail].fa = rear;
69             tail++;
70         }
71         rear++;
72     }
73 }
74 int main()
75 {
76     /*预处理*/
77     Init("12348765");
78     int T;
79     scanf("%d", &T);
80     while (T--)
81     {
82         int tmp;
83         for (int i = 0; i < 4; i++)
84         {
85             scanf("%d", &tmp);
86             ts.str[i] = tmp + '0';
87         }
88         for (int i = 4; i < 8; i++)
89         {
90             scanf("%d", &tmp);
91             ts.str[(8 - i) + 3] = tmp + '0';
92         }
93         ts.Contor();
94         printf("%d
", Map[ts.val] - 1);
95     }
96     return 0;
97 }
他坐在湖边,望向天空,她坐在对岸,盯着湖面
原文地址:https://www.cnblogs.com/Inkblots/p/5093255.html