POJ 3134 Power Calculus (IDA*)

题目类型  搜索题(IDA*)

题目意思
起始的值是 x 问至少经过多少次操作能得到 x ^ n
每次操作是在上一次操作的基础上乘以或除以之前算出过的 x 的幂
例如输入 n = 2的话只需一次 即 x * x = x ^ 2 
输入n = 31的话要  6 次操作
第1步 x * x = x ^ 2
第2步 x^2 * x^2 = x ^ 4
第3步 x^4 * x^4 = x ^ 8
第4步 x^8 * x^8 = x ^ 16
第5步 x^16 * x^16 = x^32
第6步 x^32 / x = x ^ 31

解题方法
那么可以用迭代加深 + A*  剪枝的方法来做 即 IDA*
不断加大搜索的深度 每层搜索就用前一步得出的值和之前产生的所有值进行乘或除运算得出新的值
剪枝 : 假设当前已经算出来的x的幂的次方数最大是 n_max 那么如果还可以深入搜索 3 层的话 x 的次方数最多只可能变成 n_max << 3 
            所以如果 n_max << (还剩下的搜索层数) < n 的话已经没有继续搜索的必要 回退

参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int maxH, n, nc, n_max;
int num[110];

bool DFS(int tc) {
	if(num[nc-1] == n) return true;
	if(n_max * (1<<(maxH-tc)) < n) return false;
	if(tc == maxH) return false;
	for( int i=0; i<nc; i++ ) {
		num[nc] = num[nc-1] + num[i]; nc++;
		int tmp = n_max;
		n_max = max(n_max, num[nc-1]);
		if(DFS(tc+1)) return true;
		n_max = tmp;
		nc--;
	}
	for( int i=0; i<nc; i++ ) {
		num[nc] = num[nc-1] - num[i]; nc++;
		if(DFS(tc+1)) return true;
		nc--;
	}
	return false;
}

int main() {
	while(scanf("%d", &n), n) {
		maxH = 0;
		num[nc=0] = 1; nc = 1;
		while(DFS(0) == false) {
			num[nc=0] = 1;
			n_max = 1;
			nc = 1;
			maxH++;
		}
		printf("%d\n", maxH);
	}
	return 0;
}

你可能感兴趣的:(搜索)