【题目描述】
风水是中国民间一种古老的学问,有人将之奉若神明,有人则认为这是迷信,谁知道呢!不管怎样,在当今社会,每一个人都应该尊重我们的老祖先传下来的宝贵文化。
风水主要关注地形,环境,以及相关的位置,其所有理论都来自一本古老的书,那就是《易经》,“易”意识着转变,世上所有事物都在变化,风水学希望能引导改变,从而使我们的生活变得更加美好。现在让我们看看风水的变化。
首先,我们必须了解风水学中构成万物的5大元素:金(GOLD),木(WOOD),土(GROUND),水(WATER),火(FIRE),世间万物皆由其中一种元素(仅有一种)所代表,比如:河流的代表元素是水,山的代表元素是土,在这里,我们着重考虑这些元素。在这个体系中,某种元素会“克”(Kill)另一种元素,而某种元素也会“生”(Born)另一种元素,这种相克相生的关系可以用下面两个环来描述:
每个位置有8个方向:东(east)、西(west)、南(south)、北(north)、东北(northeast)、西北(northwest)、东南(southeast)和西南(southwest),每个方向也有一个代表元素。现在我们的问题是有关风水中的方向及其代表元素的。下面图a就是这样一个例子:
但是风水是会变的,可以通过下面两种方式改变:
(1)旋转(TURN):把整个方位沿顺时针方向旋转一下,下图b显示了图a经过一次旋转操作的结果。
(2)重生(REBORN):基于上面的相生相克关系,某个方向上的代表元素会被另一个任意位置的元素克,那么被克的元素会在原位置生出一种新的元素,当然了,所有的克与生均遵循上图所述的关系。下图b中位于东南的火会被位于东方的水相克,因此东南方位的元素会变成土,如下图c:
每一次改变,不管是旋转还是重生,代价均为1。 现在,给你两个风水图,我们想知道其中第一个能否转变为第二个,如果能,最小代价是多少?
【输入格式】
输入数据共有6行组成,前3行表示第一个风水图,后3行表示第二个风水图。
风水图的8个方向如下所示,在两个相邻方向之间可能会有多个空格。
northwest north northeast
west east
southwest south southeast
【输出格式】
一行,输出其转变的最小代价,如果无法转变,输出-1。
【样例输入】
GOLD WOOD WATER
WATER FIRE
WOOD GOLD GROUND
WATER GOLD WOOD
WOOD WATER
GOLD GROUND GROUND
【样例输出】
2
将状态转化为有规律的直观数据 可转化为0,1,2,3,4的五进制
旋转操作::任选一起点顺时针或逆时针集成一个八位五进制数,自己定义状态如,可自定义。由此计算出自定义的状态值。
如图状态值可计算状态值为a=0*5^0+1*5^1+3*5^2+4*5^3+……+3*5^7=251830 则顺时针旋转后状态置为b=87278 b=a%5^7*5+a/5^7 ;已知状态值,求对应状态所对应布局时,将状态值不断对5取mod即可。
对应一个数i,克它的数为(i+4)%5。它则变成为i'=(i+3)%5。
时间复杂度为O(N*M^N).
5进制相当于散列函数,防冲突。
code 注:代码我wa了无数次,此代码是KZNS大神的。
1.题解
2.#include <cstdio>
3.#include <queue>
4.using namespace std;
5./*
6.GOLD = 0
7.WOOD = 1
8.GROUND = 2
9.WATER = 3
10.FIRE = 4
11.*/
12.int BK[5] = {4, 0, 1, 2, 3};
13.int BN[5] = {3, 4, 0, 1, 2};
14.int C5[9] = {1, 5, 25, 125, 625, 3125, 15625, 78125, 390625};
15.int S, T;
16.int ud[400000];
17.int gtp(char *C) {
18. if (C[0] == 'G')
19. if (C[1] == 'O')
20. return 0;
21. else
22. return 2;
23. else
24. if (C[0] == 'W')
25. if (C[1] == 'O')
26. return 1;
27. else
28. return 3;
29. else
30. return 4;
31.}
32.void init() {
33. char C[8][10];
34. int tls[8] = {0, 1, 2, 7, 3, 6, 5, 4};
35. for (int i = 0; i < 8; i++)
36. scanf("%s", C[tls[i]]);
37. for (int i = 0; i < 8; i++)
38. S = S*5 + gtp(C[i]);
39.
40. for (int i = 0; i < 8; i++)
41. scanf("%s", C[tls[i]]);
42. for (int i = 0; i < 8; i++)
43. T = T*5 + gtp(C[i]);
44.}
45.void work() {
46. if (S == T) {
47. printf("0\n");
48. return;
49. }
50. queue<int> ls;
51. ls.push(S);
52. ud[S] = 1;
53. int u, t;
54. int x;
55. while (!ls.empty()) {
56. u = ls.front();
57. ls.pop();
58. t = u/5 + u%5*C5[7];
59. if (!ud[t]) {
60. ud[t] = ud[u] + 1;
61. ls.push(t);
62. if (t == T)
63. break;
64. }
65.
66. bool hv[5] = {false};
67. t = u;
68. for (int i = 0; i < 8; i++) {
69. hv[t%5] = true;
70. t /= 5;
71. }
72. t = 0;
73. for (int i = 0; i < 8; i++) {
74. x = u / C5[i] % 5;
75. if (hv[BK[x]])
76. x = BN[x];
77. t = u/C5[i+1]*C5[i+1] + x*C5[i] + u%C5[i];
78. if (!ud[t]) {
79. ud[t] = ud[u] + 1;
80. ls.push(t);
81. if (t == T)
82. break;
83. }
84. }
85. }
86. printf("%d\n", ud[T] - 1);
87.}
88.int main() {
89. freopen("fengshui.in", "r", stdin);
90. freopen("fengshui.out", "w", stdout);
91. init();
92. work();
93. return 0;
94.}