zoukankan      html  css  js  c++  java
  • UVA529 Addition Chains


    题意:

    一个与 nn 有关的整数加成序列 $<a_0,a_1,a_2,...,a_m>$ 满足以下四个条件:
    1.$a_0=1$

    2.$a_m=n$
    3.$a_0<a_1<a_2<...<a_{m-1}<a_m$
    4. 对于每一个 k(1≤k≤m) 都存在有两个整数 i 和 j(0≤i,j≤k-1,i和 j 可以相等 ) ,使得 $a_k=a_i+a_j$​
    你的任务是:给定一个整数 nn ,找出符合上述四个条件的长度最小的整数加成序列。

    如果有多个满足要求的答案,只需要输出任意一个解即可。
    举个例子,序列<1,2,3,5> 和 <1,2,4,5> 均为 n=5 时的解。

    一看就是搜索,于是爆搜。。。

    然而,这是个迭代加深搜索。。。

    剪枝如下:


    1.优化搜索顺序
    显然倒序枚举更有可能得到可行解。

    让数大一些,尽可能接近n;

    2.排除不可行解
    我们发现,对于加成数列的要求还有一个,即 $a_m=n$

    假设当前已经通过枚举得出了 $a_i$ ,正准备搜索第 i+1 个数。

    考虑通过当前形势下到第 m 项可以得到的最大值,显然,$max(a_{i+1})=a_i+a_i=2×a_i$​

    $max(a_{i+2})=a_{i+1}+a_{i+1}=2×a_{i+1}=4×a_i=2^2×a_i$​

    故由递推可得

    $max(a_m)=2^{m-i}×a_i$​

    所以在进行对 i+1 个数的搜索前,计算一下 $max(a_m)$ 是否可以达到 n ,

    如果达不到则无需进行下一步的搜索。

    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define love_nmr 0
    int n;
    bool flag;
    int ans[10050];
    int maxx;
    inline void print()
    {
        for(int i=1;i<maxx;i++)
            printf("%d ",ans[i]);
        printf("%d
    ",ans[maxx]);
    }
    inline void dfs(int depth,int pos)
    {
        if(depth==maxx+1)
        {
            if(ans[maxx]==n)
                flag=true;
            return;    
        }
        for(int i=depth-1;i>=pos;i--)
        {
            for(int j=i;j>=1;j--)
            {
               int f=ans[depth]=ans[i]+ans[j];
               for(int is=pos+1;is<=maxx;is++) f<<=1;
               if(f<n)break;
               dfs(depth+1,i+1);
               if(flag)return;
               ans[depth]=0;
            }
        }
    }
    int main()
    {
        while(~scanf("%d",&n)&&n)
        {
            if(n==1)
            {
                printf("1
    ");
                continue;
            }
            flag=false;
            ans[1]=1;
            for(int i=2;i<=n;i++)
            {
                maxx=i;
                dfs(2,1);
                if(flag)
                {
                    print();
                    break;
                }
            }
        }
    }
  • 相关阅读:
    Window 窗口类
    使用 Bolt 实现 GridView 表格控件
    lua的table库
    Windows编程总结之 DLL
    lua 打印 table 拷贝table
    使用 xlue 实现简单 listbox 控件
    使用 xlue 实现 tips
    extern “C”
    COleVariant如何转换为int double string cstring
    原来WIN32 API也有GetOpenFileName函数
  • 原文地址:https://www.cnblogs.com/olinr/p/9429690.html
Copyright © 2011-2022 走看看