zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    移动网络优化
    移动网络架构与数据传输
    移动网络简介与RRC
    CSS之外边距折叠
    网络协议之TLS
    Smarty 模板引擎简介
    FormData介绍
    相对路径与绝对路径
    OAuth2.0
    Redis学习手册(List数据类型)
  • 原文地址:https://www.cnblogs.com/littlehb/p/15656925.html
Copyright © 2011-2022 走看看