• Addition Chains


    题目描述:

    一个与 n 有关的整数加成序列 < a0 , a1 , a2 ...am> 满足一下四个条件:

    1.a0=1

    2.am=n

    3.a0<a1<a2<...<am

    4.对于每个( 1≤k≤m )都存在有两个整数 i 和 j (0 ≤ i , j  ≤ k - 1 , i 和 j可以相等),使得ak=ai+aj

    你的任务是:给定一个整数 n ,找出符合上述四个条件的长度最小的整数加成序列。如果有多个满足要求的答案,只需要输出任意一个解即可。

    举个例子:序列< 1,2,3,5 >和< 1,2,4,5 >均为 n = 5 时的解

    输入格式:

    多组数据,每行给定一个正整数n。输入以0结束。

    输出格式:

    对于每组数据,输出满足条件的长度最小的数列。

    样例输入:

    5

    7

    12

    15

    77

    0

    样例输出:

    1 2 4 5

    1 2 4 6 7

    1 2 4 8 12

    1 2 4 5 10 15

    1 2 4 8 9 17 34 68 77

    思路:

      看了书之后才知道这题是用搜索。(蒟蒻的我只会暴力枚举

      那么怎么搜索又成为了一个问题——其实可以依次搜索一位k, 枚举之前的i, j, 把a[i] + a[j] 加到a[k]的位置上, 然后接着搜索;

      这样还是AC不了。

      这时就需要考虑剪枝。

      对于剪枝:

      ①尽量从达到小枚举i,j让序列的数尽快逼近n;(贪心思想)

      ②为了不重复搜索,用一个bool数组存a[i] + a[j] 是否已经被搜过;

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdlib>
    #include<iostream>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<vector>
    #include<map>
    #include<set>
    using namespace std;
    #define maxn 1100
    int n,ans,a[maxn];
    bool use[maxn];
    inline int read()
    {
        char kr=0;
        char ls;
        for(;ls>'9'||ls<'0';kr=ls,ls=getchar());
        int xs=0;
        for(;ls>='0'&&ls<='9';ls=getchar())
        {
            xs=xs*10+ls-48;
        }
        if(kr=='-') xs=0-xs;
        return xs;
    }
    inline bool dfs(int stp)
    {
        memset(use,0,sizeof(use));
        if(stp>ans)
        {
            if(a[ans]==n) return true;
            else return false;
        }
        for(register int i=stp-1;i>=1;i--)
        {
            for(register int j=i;j>=1;j--)
            {
                if(a[i]+a[j]>n) continue;
                if(!use[a[i]+a[j]])
                {
                    if(a[i]+a[j]<=a[stp-1]) return false;
                    use[a[i]+a[j]]=true;
                    a[stp]=a[i]+a[j];
                    if(dfs(stp+1)) return true;
                    a[stp]=0;
                    use[a[i]+a[j]]=false;
                }
            }
        }
    }
    int main()
    {
        while(n=read(),n!=EOF)
        {
            if(n==0) return 0;
            if(n==1)
            {
                printf("1
    ");
                continue;
            }
            if(n==2)
            {
                printf("1 2
    ");
                continue;
            }//特判一下上述三种情况 
            a[1]=1;a[2]=2;
            for(ans=3;!dfs(3);ans++);//搜索记录 
            for(register int i=1;i<=ans;i++)
            {
                printf("%d ",a[i]);
            }
            printf("
    ");
            memset(a,0,sizeof(a));
        }
    return 0;
    }

    洛谷谜一般的评测TLE,在POJ上提交AC了。

  • 相关阅读:
    Openstack----学习笔记
    如何往gitlab/github上游贡献代码
    搭建python虚拟环境virtualenv
    YAML格式
    mysql安装
    使用mysql服务实现负载均衡
    tomcat web服务的搭建
    通过SQL查询SQL服务器和客户端IP地址
    验证数字的正则表达式
    C# WinForm控件美化扩展系列之给TextBox加水印
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9648379.html
Copyright © 2020-2023  润新知