描述
有一个数列,具有这样的性质: a1 = 1 ,对于数列中的其他数 ak= ai + aj (1<=i<=j<=n )
题目
现在给出数列的最后一个数an,求使 n 最小的数列。
输入输出格式
输入
一行,只有一个整数 an , ( 1 <= n <= 1000 )
输出
第一行输出 n 。第二行输出数列,每两个数之间有且仅有一个空格。
输入输出样例
输入样例1
4
输出样例1
3
解题思路
刚开始读题的时候差点没读懂,简单来讲就是每一个数都有它前面任意两个数组成,并且要大于它前一个数(虽然题没说,但是你越加越少的话那你还加个什么劲儿,直接剪枝剪掉),给你an,问你这一列数最少几个才能满足条件。这道题还是极大化剪枝,每次将读进来的数不断乘2(前一个数加上前一个数),模拟最优方法,如果步数比当前最优的大,那就返回。
题解
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,ans=999999; 4 int dp[1001];//存储数列 5 void dfs(int dep,int pre)//搜索深度(这一列数的第几个)和前一个数的值 6 { 7 int sum=-1;//因为这时的dep是加上这个数的深度,已经赋值的深度就是dep-1,这里的赋值代替了减一操作 8 int p=pre; 9 while(p<=n) 10 { 11 p*=2;//模拟最优策略 12 sum++; 13 } 14 if(dep+sum>=ans)return;//极大化剪枝 15 for(int i=dep-1;i>=1;i--)//循环枚举两个加数,这里我是倒着枚举的,因为从一开始的话会重复很多没用的 16 { 17 for(int j=i;j>=1;j--) 18 { 19 int num=dp[i]+dp[j]; 20 if(num>pre&&num<=n)//比前一个数大并且没有超出an 21 { 22 dp[dep]=num;//存储 23 if(num==n&&dep<ans)//满足条件还更优 24 { 25 ans=dep;//替换 26 return; 27 } 28 dfs(dep+1,num);//继续搜索 29 } 30 } 31 } 32 } 33 int main() 34 { 35 ans=99999;//初始化 36 cin>>n; 37 if(n<=2)//小于2直接输出 38 { 39 cout<<n; 40 return 0; 41 } 42 dp[1]=1; 43 dp[2]=2;//因为2前面只有1,所以1+1=2 44 dfs(3,2);//从第三个数开始,第三个数前一个是2 45 cout<<ans; 46 47 }