• Addition Chains


    POJ n<=100

    洛咕 n<=10000

    题意:满足如下条件的序列a被称为"加成序列":

    (1.a_1=1)

    (2.a_m=n)

    (3.a_1<a_2<...<a_{m-1}<a_m)

    (4.)对于每一个(k(1≤k≤m))都存在有两个整数 (i)(j(1≤i,j≤k-1,i)(j) 可以相等 ) ,使得 (a_k=a_i+a_j)

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

    分析:显然,(a[1]=1,a[2]=2),这两个可以直接特判,然后我们从序列的第3位开始搜起.设当前搜索到了位置k,我们直接枚举i和j,然后(a[k]=a[i]+a[j]).暴力的搜索框架就是这样.下面考虑优化.

    序列的长度可以直接看做搜索深度,所以我们可以迭代加深,搜索深度从3开始每次加1,直到搜到一个合法的序列为止.

    然后还有一些必要的剪枝:

    剪枝一:枚举i和j时从大到小枚举,以便于更快地逼近n,减少状态数.

    剪枝二:因为我们是从大到小枚举,所以如果当前的(a[i]+a[i])或者(a[i]+a[j])小于(a[now-1])(保证序列单调递增),就可以直接break掉了.因为后面的只会更小.

    剪枝三:对于不同的i和j,(a[i]+a[j])可能相等,如果当前填入(a[i]+a[j])搜索失败了,我们就标记一下,下次就不再填入这个数了.

    剪枝四:因为(a[now])最多是(a[now-1])的两倍,所以如果我们发现每次都填最大仍会导致第dep位比n小,那么直接return 掉.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    int n,dep,a[10005];
    inline bool dfs(int now){
    	if(now>dep){
    		if(a[dep]==n)return true;
    		return false;
    	}
    	if(a[now-1]*(1<<(dep-now+1))<n)return false;//剪枝4
    	map<int,int>fail;//剪枝3
    	for(int i=now-1;i>=1;--i){//剪枝1的倒序枚举
    		if(a[i]+a[i]<=a[now-1])break;//剪枝2
    		for(int j=i;j>=1;--j){//避免重复,从第i位开始
    			if(a[i]+a[j]<=a[now-1])break;//剪枝2
    			if(a[i]+a[j]<=n&&!fail[a[i]+a[j]]){
    				a[now]=a[i]+a[j];
    				if(dfs(now+1))return true;
    				fail[a[i]+a[j]]=1;//剪枝3的标记操作
    				a[now]=0;
    			}
    		}
    	}
    	return false;
    }
    int main(){
    	while(1){
    		n=read();if(!n)break;
    		if(n==1){puts("1");continue;}
    		if(n==2){printf("1 2
    ");continue;}
    		a[1]=1;a[2]=2;dep=3;
    		while(1){//迭代加深,从3开始
    			if(dfs(3))break;
    			++dep;
    		}
    		for(int i=1;i<dep;++i)printf("%d ",a[i]);
    		printf("%d
    ",a[dep]);
    	}
        return 0;
    }
    
    
  • 相关阅读:
    JAVA-throw new IOException报错unhandled exception:java.lang.Exception 2021年6月7日
    GIt保持远程 源仓库与Fork仓库同步--2017年6月13日
    Python的getattr()-2017年6月7日
    JavaScript学习-2017年5月18日
    Writing your first Django app--2017年5月9日
    M4-AC6 Oh,Trojan Again--2017年5月9日
    吴军硅谷来信
    【1】Prologue--A Game of Thrones--2017年4月8日
    M4-PC9 Read 10,000 Books,Travel 10,000 Miles--2017年5月8日
    资源分配图RAG的化简
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11388809.html
Copyright © 2020-2023  润新知