例题7-12 旋转游戏(The Rotation Game, Shanghai 2004, UVa1343)

如果用bfs进行状态空间搜索,分三次搜索,每次的状态数为C(24, 8) = 735471。
每次只存8个点的位置,并映射为一个16位的longlong,用set来判重。
状态搜索时,打一个表,对应24个坐标与8种移动的关系。
映射成longlong与解码的代价都不小,感觉不太行。
用IDA*来搜索,乐观估值函数定义为centre中最少的不同数的个数,每次最多修改一个。

对于这种状态数超多的搜索,IDA*是不错的选择。

无论是代码长度,还是时间复杂度,都有不少的优化。

#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <utility>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <cctype>
#define CLEAR(a, b) memset(a, b, sizeof(a))
#define IN() freopen("in.txt", "r", stdin)
#define OUT() freopen("out.txt", "w", stdout)
#define LL long long
#define mod 1000000007
#define INF 1000000007
#define eps 1e-5
#define PI 3.1415926535898
using namespace std;
//-------------------------CHC------------------------------//
const int line[8][7] = { { 0, 2, 6, 11, 15, 20, 22 }, { 1, 3, 8, 12, 17, 21, 23 },
					     { 10, 9, 8, 7, 6, 5, 4 }, { 19, 18, 17, 16, 15, 14, 13 },
					     { 23, 21, 17, 12, 8, 3, 1 }, { 22, 20, 15, 11, 6, 2, 0 },
					     { 13, 14, 15, 16, 17, 18, 19 }, { 4, 5, 6, 7, 8, 9, 10 } };
const int centre[] = { 6, 7, 8, 11, 12, 15, 16, 17 };
int a[24], maxd;
char ans[1005];

bool check() {
	for (int i = 1, x = a[centre[0]]; i < 8; ++i)
		if (a[centre[i]] != x) return false;
	return true;
}

int differ(int t) {
	int ret = 0;
	for (int i = 0; i < 8; ++i)
		if (a[centre[i]] != t) ret++;
	return ret;
}

int h() { return min(differ(1), min(differ(2), differ(3))); }

void rotate(int t) {
	int temp = a[line[t][0]];
	for (int i = 0; i < 6; ++i)
		a[line[t][i]] = a[line[t][i + 1]];
	a[line[t][6]] = temp;
}

bool dfs(int d) {
	if (check()) {
		for (int i = 0; i < d; ++i)
			putchar(ans[i]);
		return true;
	}
	if (d + h() > maxd) return false;
	int t[24];
	memcpy(t, a, sizeof(a));
	for (int i = 0; i < 8; ++i) {
		ans[d] = i + 'A';
		rotate(i);
		if (dfs(d + 1)) return true;
		memcpy(a, t, sizeof(a));
	}
	return false;
}

int main() {
	while (~scanf("%d", &a[0]) && a[0]) {
		for (int i = 1; i < 24; ++i)
			scanf("%d", &a[i]);
		if (check()) printf("No moves needed");
		else {
			for (maxd = 1; ; ++maxd)
				if (dfs(0)) break;
		}
		printf("\n%d\n", a[centre[0]]);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值