埃及分数 + IDA*算法

以下的所有观点并不完全正确,只是个人的主观理解,请读者谨慎阅读:
IDA算法:
该算法为dfs算法的变种。首先设置一个深度上界maxH,设当前深度h(x),估界函数为g(x),当且仅当 h(x) + g(x) > maxH时表示该分支不可能有解应该剪掉该分支回溯回去。 如果在当前深度上界不能得到解,则增加深度上界的值,直到得到解。
为何? 该算法得到解为最优解呢? 我个人观点:IDA
算法跟普通的dfs的区别就是:“IDA*算法将 dfs要遍历的深度进行了分割,这样可以剪掉许多不必要的分支,从而比普通的dfs要快,并且在有些题目中遍历的深度与广度没有界限,很难正确的设计回溯算法,这时候就要分割深度,将深度看作一个一个的界限,然后枚举这些界限直达找到答案。” 分割深度需要找到一个合适的估计上界的函数。 一般的操作是: 求最大值则假设一个合法的最小值,然后除以剩余值得到 g(x) ;求最小值时则相反。 埃及分数就是一个“求最小值”的例子

参考紫书上的代码:

#include<iostream>
#include<string.h>
#include<algorithm>
typedef long long LL;
using namespace std;
int maxd;
LL ans[100], v[100];
int get_first(int n, int m) {
	int a = 2;
	while (n * a < m) a++;
	return a;
}
bool compare(int floor) {
	for (int i = floor; i >= 0; i--) {
		if (v[i] != ans[i])
			return ans[i] == -1 || v[i] < ans[i];
	}
}
int gcd(int n2, int m2) {
	return m2 % n2 ? gcd(m2 % n2,n2) : n2;
}
bool dfs(int floor, int fm, LL n, LL m) {
	if (floor == maxd) {
		if (m % n) return false;
		v[floor] = m / n;
		if (compare(floor)) memcpy(ans, v, sizeof(LL) * (floor + 1));
		return true;
	}
	bool ok = false;
	fm = max(fm, get_first(n, m));
	for (int i = fm; ; i++) {
		if (m * (maxd + 1 - floor) <= i * n) break;  //估计可能还需要向下几层, 如果超过了则结束
		LL n2, m2;
		v[floor] = i;
		n2 = n * i - m;
		m2 = m * i;
		LL b = gcd(n2, m2);
		if (dfs(floor + 1, i + 1, n2 / b, m2 / b)) ok = true;
	}
	return ok;
}
void print(int floor,int n, int m) {
	printf("%d/%d=1/%d", n, m,ans[0]);
	for (int i = 1; i <= floor; i++) {
		printf("+1/%d", ans[i]);
	}
	cout << endl;
}
int main() {
	LL n, m;
	while (cin >> n >> m) {
		for (maxd = 1; ; maxd++) {//枚举所有的深度上界,如果有解则一个会有一个深度上界可以退出循环,  递归的深度就是当前深度上界。
			memset(ans, -1, sizeof(ans));
			if (dfs(0, get_first(n, m), n, m)) {
				print(maxd, n, m);
				break;
			}
		}
	}
	return 1;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值