UVA529 Addition Chains[加法链]

题目传送门

一、题目分析

1、迭代加深

看完题目第一反应求最短路:\(bfs\);看了一眼\(n=10000\),肯定会爆空间。

因此考虑\(dfs\),用\(dfs\)求最短路径,那不就是暗示我们使用迭代加深嘛~

2、剪枝

不难看出需要的序列是单调递增的,枚举\(i\),\(j\)得到\(t\);因此如果发现\(ans[i]+ans[j]>n\) 或者 \(ans[i]+ans[j] <= a[k-1]\),那都不需要\(k\)位出手。

强剪枝:\(ans[i]<=ans[i-1]*2\),也就是说后一项最多是前一项的\(2\)倍,如果当前已知\(ans[k]\)然后迭代加深的最大深度为\(pos\),则后面最多还有\(pos-k\)项,也就是说\(ans[k]*2^k<n\)则在\(pos\)次之内一定找不到答案。

二、实现代码

#include<bits/stdc++.h>

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] && t <= n) {
                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;
}
原文地址:https://www.cnblogs.com/littlehb/p/15656925.html