迭代加深搜索-埃及分数问题


每天坚持做算法题,熟悉基本的套路,巩固语言基础,总结经验记下所学所想。

题目

HINT

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
const int maxn = 1000
int ans[maxn], v[maxn];

//满足1/c≤a/b的最小c
int get_first(int a, int b){
for(int i = 1; ;++i){
if(1/i <= a/b) return i;
}
}

//如果当前解v比目前最优解ans更优,更新ans
bool better(int d) {
for(int i = d; i >= 0; i--) if(v[i] != ans[i]) {
return ans[i] == -1 || v[i] < ans[i];
}
return false;
}

//当前深度为d,分母不能小于from,分数之和恰好为aa/bb
//往一个方向收敛则无需判重
bool dfs(int d, int from, LL aa, LL bb) {
if(d == maxd) {
if(bb % aa) return false; //aa/bb必须是埃及分数
v[d] = bb/aa;
if(better(d)) memcpy(ans, v, sizeof(LL) * (d+1));
return true;
}

bool ok = false;
from = max(from, get_first(aa, bb)); //枚举的起点
for(int i = from; ; i++) {
//剪枝:如果剩下的maxd+1-d个分数全部都是1/i,加起来仍然不超过aa/bb,则无解
if(bb * (maxd+1-d) <= i * aa) break;
v[d] = i;
//计算aa/bb - 1/i,设结果为a2/b2
LL b2 = bb*i;
LL a2 = aa*i - bb;
LL g = gcd(a2, b2); //以便约分
if(dfs(d+1, i+1, a2/g, b2/g)) ok = true;
}
return ok;
}

int main(){
int maxd;
int a,b;
cin>>a>>b;

int ok = 0;
for(maxd = 1; ; maxd++) {
memset(ans, -1, sizeof(ans));
if(dfs(0, get_first(a, b), a, b)) { ok = 1; break; }
}

for(int i = 0; i<maxn; ++i){
if(v[i]){
cout<<v[i]<<" ";
}else break;
}
return 0;
}

总结

-------------本文结束感谢您的阅读-------------

本文标题:迭代加深搜索-埃及分数问题

文章作者:ChengXiao

发布时间:2018年04月17日 - 22:04

最后更新:2018年09月03日 - 22:09

原始链接:http://chengxiao19961022.github.io/2018/04/17/迭代加深搜索-埃及分数问题/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

你的鼓励是我前进的动力~