uva 1343(bfs+hash+打表)

按照《算法竞赛入门经典》书的思路写的代码, 但很却很遗憾,最终还是WA了, 可以用IDA*写这题, 思路清晰且代码清晰易懂。

dfs算法:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
using namespace std;
struct cNode {
	int next;
	int v;
};
struct Node {
	int chess[24];
	int steps;
	string succession;
	bool operator <(const Node& t1) const {
		return steps > t1.steps;
	}
};
const int classify[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 mid[8] = { 6,7,8,11,12,15,16,17 };
char letter[8] = { 'A','F','B','E','H','C','G','D' };
int chess[24];
int bestSteps;
int maxn = 1000000;
int head[1000000];
vector<cNode> vec;
void init() {
	memset(head, -1, sizeof(head));
	vec.clear();
}

bool try_(Node& t1) {
	int v = 0;
	//压缩了状态,24位压缩成了8位, 就取中间的8位,很显然运行速快了,但是结果就不正确了,具体修改我也不知道。
	//状态是否能压缩,取决于某些状态于某些状态的扩展结点是相同的;换句话说: 当某些状态于某些状态的扩展结点相同,他们可以被压缩成一种状态表示;
	for (int i = 0; i < 8; i++) {
		v = v << 1;
		if (t1.chess[mid[i]]) v += 1;
	}
	cNode temp;
	int h = v % maxn;
	int u = head[h];
	while (u != -1) {
		if (vec[u].v == v)
			return false;
		u = vec[u].next;
	}
	temp.next = head[h];
	temp.v = v;
	vec.push_back(temp);
	head[h] = vec.size() - 1;
	return true;
}

bool isResult(Node& t, int curi) {
	for (int i = 0; i < 8; i++) {
		if (t.chess[mid[i]] != curi)
			return false;
	}
	return true;
}

void bfs(int& steps, string& succession2, int curi) {
	priority_queue<Node> q;
	Node newnode;
	newnode.steps = 0;
	newnode.succession = "";
	memcpy(newnode.chess, chess, sizeof(int) * 24);
	q.push(newnode);
	init();
	try_(newnode);

	while (!q.empty()) {
		Node top = q.top();
		q.pop();
		if (top.steps >= bestSteps)
			return;
		if (isResult(top, curi)) {
			steps = top.steps;
			succession2 = top.succession;
			return ;
		}
		for (int i = 0; i < 8; i++) {
			memcpy(newnode.chess, top.chess, sizeof(int) * 24);
			newnode.steps = top.steps + 1;
			newnode.succession = top.succession;
			newnode.succession.push_back('A' + i);
			int tmp = newnode.chess[classify[i][0]];
			for (int j = 0; j < 6; j++)  newnode.chess[classify[i][j]] = newnode.chess[classify[i][j + 1]];
			newnode.chess[classify[i][6]] = tmp;
			if (try_(newnode)) {
				q.push(newnode);
			}
		}
	}
}
int main() {
	int firstChess[24],num;
	string succession2,succession;
	while (cin >> firstChess[0] && firstChess[0] != 0) {
		for (int i = 1; i < 24; i++)
			cin >> firstChess[i];
		bestSteps = maxn;
		for (int i = 1; i <= 3; i++) {
			int steps = 0;
			for (int j = 0; j < 24; j++)
				if (firstChess[j] != i) {
					chess[j] = 0;
				}
				else
					chess[j] = i;
			bfs(steps, succession2, i);
			if (bestSteps > steps && steps != 0) {
				bestSteps = steps;
				succession = succession2;
				num = i;
			}
		}

		cout << succession << "\n" << num << endl;
	}
}

IDA*算法

// UVa1343 The Rotation Game

// Rujia Liu

// This solutions uses IDA* instead of BFS described in the book, because it's shorter 8-)

// It's shorter because no need for lookup tables and "automatically" lexicographically smallest solution.

#include<cstdio>

#include<algorithm>

using namespace std;



/*

      00    01

      02    03

04 05 06 07 08 09 10

      11    12

13 14 15 16 17 18 19

      20    21

      22    23

*/



// lines E~H are computed with the help of rev[]

int line[8][7]={

  { 0, 2, 6,11,15,20,22}, // A

  { 1, 3, 8,12,17,21,23}, // B

  {10, 9, 8, 7, 6, 5, 4}, // C

  {19,18,17,16,15,14,13}, // D

};



const int rev[8] = {5, 4, 7, 6, 1, 0, 3, 2}; // reverse lines of each line



// center squares

const int center[8] = {6, 7, 8, 11, 12, 15, 16, 17};



int a[24];

char ans[1000];



bool is_final() {

  for(int i = 0; i < 8; i++)

    if (a[center[i]] != a[center[0]]) return false;

  return true;

}



int diff(int target) {

  int ans = 0;

  for(int i = 0; i < 8; i++)

    if(a[center[i]] != target) ans++;

  return ans;

}



inline int h() {

  return min(min(diff(1), diff(2)), diff(3));

}



inline void move(int i) {

  int tmp = a[line[i][0]];

  for(int j = 0; j < 6; j++) a[line[i][j]] = a[line[i][j+1]];

  a[line[i][6]] = tmp;

}



bool dfs(int d, int maxd) {

  if(is_final()) {

    ans[d] = '\0';

    printf("%s\n", ans);

    return true;

  }

  if(d + h() > maxd) return false;

  for(int i = 0; i < 8; i++) {

    ans[d] = 'A' + i;

    move(i);

    if(dfs(d+1, maxd)) return true;

    move(rev[i]);

  }

  return false;

}



int main() {

  for(int i = 4; i < 8; i++)

    for(int j = 0; j < 7; j++) line[i][j] = line[rev[i]][6-j];



  while(scanf("%d", &a[0]) == 1 && a[0]) {

    for(int i = 1; i < 24; i++) scanf("%d", &a[i]);

    for(int i = 0; i < 24; i++) if(!a[i]) return 0;

    if(is_final()) {

      printf("No moves needed\n");

    } else {

      for(int maxd = 1; ; maxd++)

        if(dfs(0, maxd)) break;

    }

    printf("%d\n", a[6]);

  }

  return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值