uva 1343 IDA*

转载别人的:

从小到大依次枚举深度上限maxd。对于每一个深度上限,进行dfs,当递归到maxd时,就要判断是否找到了解,如果找到了,就记录或者输出解。不论是否找到了解,都要开始返回,对于找到了解的情况,可以在函数出口处连续返回。
那么如何及时的返回呢?答案就是寻找“估价函数”并“剪枝”。对于本题,可以发现,每次移动最多只能让目标数字多1个,因此可以将min{diff(1),diff(2),diff(3)}作为估价函数。其中diff(i)是目标格子中不等于数字i的个数。这样以来,如果发现最少要移动的步数h()仍然大于maxd-cur,就需要进行剪枝。

#include <bits/stdc++.h>
using namespace std;
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},
};
const int rev[8] = {5, 4, 7, 6, 1, 0, 3, 2};
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';
		cout << ans << endl;
		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(int argc, char const *argv[])
{
	for (int i = 4; i < 8; i++)
		for (int j = 0; j < 7; j++)
			line[i][j] = line[rev[i]][6 - j];//初始化E-G
	while (cin >> a[0] && a[0])
	{
		for (int i = 1; i < 24; i++)
			cin >> a[i];
		for (int i = 0; i < 24; i++) if (!a[i]) return 0;
		if (is_final())
			cout << "No moves needed" << endl;
		else for (int maxd = 1;; maxd++)
				if (dfs(0, maxd)) break;
		cout << a[6] << endl;
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值