1471. 风水 解题报告

【题目描述】

 

风水是中国民间一种古老的学问,有人将之奉若神明,有人则认为这是迷信,谁知道呢!不管怎样,在当今社会,每一个人都应该尊重我们的老祖先传下来的宝贵文化。

风水主要关注地形,环境,以及相关的位置,其所有理论都来自一本古老的书,那就是《易经》,“易”意识着转变,世上所有事物都在变化,风水学希望能引导改变,从而使我们的生活变得更加美好。现在让我们看看风水的变化。

首先,我们必须了解风水学中构成万物的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

 

将状态转化为有规律的直观数据         可转化为01234的五进制

旋转操作::任选一起点顺时针或逆时针集成一个八位五进制数,自己定义状态如,可自定义。由此计算出自定义的状态值。

如图状态值可计算状态值为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.}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值