题解 UVA529 【Addition Chains】

· · 题解

UVA529 【Addition Chains】

好像是垃圾一本通里的题目,前置知识:迭代加深搜索 不懂的可以看我博客 内附迭代加深的模板

首先 先看题目 发现是 UVA的题目,立刻反应到,输出要有格式,这也是我交了那么多次没A的理由

然后 看数据范围 1 to 10000 ,然后仔细观察这个数列 易发现这个数列不简单必须符合一个规律,就是f[n] \leq 2 * f[n-1],至于证明,可以发现等比数列1 2 4 ... 2^n的和为2*2^n-1,那么如果要不重不漏的组合出所有数,则下一位为2 * 2 ^n 这样即可以作为一个剪枝

还有几个剪枝写在code里,如果不懂可以私我

# code ``` #include <cstring> #include <cstdio> #include <algorithm> #include <iostream> using namespace std; typedef long long ll; inline ll read() { ll f = 1, x = 0;char ch; do {ch = getchar();if (ch == '-')f = -1;} while (ch > '9' || ch < '0'); do {x = x * 10 + ch - '0';ch = getchar();} while (ch >= '0' && ch <= '9'); return f * x; } const int MAX_N = 1e4 + 5; int n, a[MAX_N], maxdepth; bool dfs (int depth,int maxdepth) { if (a[depth - 1] > n) return false; if (depth == maxdepth ) return a[depth - 1] == n; //前面提到的剪枝 if (a[depth-1]*((ll)1<<(maxdepth - depth))<n)return false; bool st[MAX_N] = {0}; //枚举顺序 从大到小 这样使搜索树上端的分叉减小 for(int i = depth - 1; i >= 0; i -- ) { for(int j = i; j >= 0; j -- ) { int s = a[i] + a[j]; //保证序列严格递增 且不大于n 而且保证其未被搜索到过 减掉冗余信息 if (s > n || s <= a[depth - 1] || st[s]) continue; a[depth] = s; st[s] = true; if (dfs (depth + 1, maxdepth)) return true; } } return false; } int main () { a[0] = 1; while (cin >> n, n) { maxdepth = 1; while (!dfs(1, maxdepth)) maxdepth ++ ; cout<<a[0]; for (int i = 1; i < maxdepth; i ++ ) cout<<" "<<a[i]; cout << endl; } return 0; } ```