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

    题目描述

    原题来自:ZOJ 1937

    已知一个数列 a0,a1...ama_0,a_1...a_ma0,a1...am(其中 a0=1,am=n,a0<a1<a2<...<am−1<ama_0 = 1 , a_m = n , a_0 lt a_1 lt a_2 lt ... lt a_{m-1} lt a_ma0=1,am=n,a0<a1<a2<...<am1<am)。对于每个 kkk,需要满足 ak=ai+aja_k=a_i+a_jak=ai+aj0≤i,j≤k−10 leq i , j leq k-10i,jk1,这里 iii 与 jjj 可以相等)。

    现给定 nnn 的值,要求 mmm 的最小值(并不要求输出),及这个数列每一项的值(可能存在多个数列,只输出任一个满足条件的就可以了)。

    输入格式

    多组数据,每行给定一个正整数 nnn 。

    输入以 000 结束。

    输出格式

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

    样例

    样例输入

    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

    很好玩的题,其实不用推什么公式,虽然数据范围是100
    但是把搜索写好了,再加一点剪枝就可以
    如果说有什么问题就是我们学校的数据锅了
    下面给出代码:
    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<queue>
    using namespace std;
    inline int rd(){
        int x=0,f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    inline void write(int x){
         if(x<0) putchar('-'),x=-x;
         if(x>9) write(x/10);
         putchar(x%10+'0');
    }
    int a[100000];
    int book[100000];
    int ans,n;
    bool dfs(int step){
        memset(book,0,sizeof(book));
        if(step>ans){//剪枝,在长度超过我们所需的时候,判断是否已经完成 
            if(a[ans]==n) return 1;
            return 0;
        }
        for(int i=step-1;i>=1;i--){
            for(int j=i;j>=1;j--){//从i开始,因为可以重复 
                if(a[i]+a[j]>n) continue;//取的值必须严格小于n 
                if(!book[a[i]+a[j]]){//不能取重复的值,严格递增 
                    if(a[i]+a[j]<=a[step-1]) return 0;
                    book[a[i]+a[j]]=1;
                    a[step]=a[i]+a[j];
                    int hh=a[step];
                    for(int k=step+1;k<=ans;k++) hh*=2;//如果取这个值在所限定的个数内取最大值也到不了,就不能取 
                    if(hh<n) break;
                    if(dfs(step+1)) return 1;//递增长度,回溯 
                    a[step]=0;
                    book[a[i]+a[j]]=0;
                }
            }
        }
        return 0;
    }
    int main(){
        while(1){
            memset(a,0,sizeof(a));
            n=rd();
            if(n==0) return 0;//因为长度小,所以要特判 
            else if(n==1){
                printf("1
    ");
                continue;
            }
            else if(n==2){
                printf("1 2
    "); 
                continue;
            }
            a[1]=1;
            a[2]=2;
            for(ans=3;!dfs(3);ans++);//判断每个长度是否可行,否则加一 
            for(int i=1;i<ans;i++) printf("%d",a[i]);
            printf("%d
    ",a[ans]);
        }
        return 0;
    }
     
     
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    Django数据库 相关之select_related/prefetch_related
    Django 序列化
    Django 信号
    Django缓存配置和使用
    Django FBV/CBV、中间件、GIT使用
    学员管理系统(SQLAlchemy 实现)
    Oracle的三种高可用集群方案
    linux系统安装硬盘分区建议
    Linux下expdp自动备份
    impdp导入报错ORA-39070:无法打开日志文件
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9754047.html
Copyright © 2011-2022 走看看