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

来源:互联网 发布:hao123网络连接错误 编辑:程序博客网 时间:2024/05/18 21:47
如果用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.1415926535898using 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;}

原创粉丝点击