#include using namespace std; const int N = 10010; int n; //输入的加法链最后一个数字 int ans[N]; //结果数组 int depth; //迭代加深的最后一个索引位置,不要理解为深度层,比如 a[0] a[1] a[2] ,那么depth=2,按深度说是3 /** * 功能:迭代加深,在当前的depth深度下,尝试找出答案 * @param k 第几个数字 * @return */ bool dfs(int k) { //如果走过规定好的步骤,回头看一眼,如果最后一次放入的是n,表示成功找到,否则就是失败 if (k > depth)return ans[k - 1] == n; //最优化剪枝:后面每一项最多是前一项的2倍 //肯定无法到达的,提前干掉,可以极大提高性能! //这个优化太棒了! if (ans[k - 1] * (1 << (depth - k + 1)) < n)return false; //枚举k之前的所有数字,两两一组 for (int i = 0; i < k; i++) for (int j = i; j < k; j++) { //双重循环保证了可以遍历出两两的所有组合情况 int t = ans[i] + ans[j]; //两两之和 if (t > ans[k - 1]) { ans[k] = t; //将和加入到目标数组中,完成本位置的填充 //尝试进行下一个位置的填充 if (dfs(k + 1))return true; //如果找到答案,就终止;否则需要继续探索之 } } return false; } int main() { //优化输入 ios::sync_with_stdio(false); //加法链第一个数字是1 ans[0] = 1; //读取多组数据 while (cin >> n, n) { //遍历每个可能的到达的索引号,在找到第一个解后退出 for (depth = 0;; depth++) { //如果在当前索引号下就能成功符合要求,表示找到了最短路径,退出就可以了 if (dfs(1)) { //a[0]值是1,从a[1]开始尝试 //找到答案输出 for (int i = 0; i <= depth; i++) { //结果 printf("%d", ans[i]); //万恶的UVA,每一行最后如果带空格还WA,还需要判断一下才行 if (i < depth)printf(" "); } //每组数完事换行 printf("\n"); //找到就结束,迭代加深的套路思想噢~ break; } } } return 0; }