膜拜

XXX 每天都被无数的人膜拜,已经被连续膜拜了 n 天,他发现每天来膜拜自己的人数是一个递增的数列。第一天只有一个人来膜拜,从第二天开始的每一天来膜拜 XXX 的人数都是之前某两天的和。现在 XXX 告诉我们今天有个人来膜拜自己,让我们求使被膜拜天数最小的数列。如果有多组解,任意输出一种即可。

 

这题没有天数,直接搜索会没有范围

但其实有一个共同的特点是保证天数最小的搜索

联想到埃及分数,迭代加深是最好的选择,每次限制层数,也就是个数就可以了

但迭代加深要有限制条件的搜索

显然这道题的数列是递增的,这是一个可以说是最优化剪枝(obivously)

同时如果在该限制深度下,以最快的增速方式(也就是每天都把上一天*2)都不足以到达目标那么就可以剪枝了,也就是我们的可行性剪枝,位运算一搞就行了

这道题告诉我复习生日蛋糕打暴力可能会有惊喜

 另外能水过50分数据的贪心(错误的)

由于可以复制自己,就相当于是左移1,联想到二进制

把一个数拆成二进制的和

每次尝试要凑这个数前i项2次幂的和

例如11=1+2+8

有1了,就是前1项和

然后复制1变成2,发现要用这个幂

凑前两项和3于是1+2

搞完一次后复制2成4,4不需要,复制成8,需要,于是直接加上去就有11

简述这个错误算法就是1位答案+2,0位+1,最后总体-1

实测50(鬼知道数据怎么出的)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int n,ans,s[1001];
 7 void pr(){
 8     cout<<ans<<endl;
 9     for (int i = 1; i < ans; i++)
10         cout<<s[i]<<" ";
11     cout<<s[ans]<<endl;
12     exit(0);
13 }
14 int dfs(int depth){
15     if(s[depth-1]==n) pr();//如果搜到了符合的答案就输出
16     if(depth>ans) return 0;//限制搜索层数
17     for(int i=depth-1;i>=1;--i){
18         for(int j=depth-1;j>=i;--j){
19             s[depth]=s[i]+s[j];//今天是前面两天的和
20             if(s[depth]<<(ans-depth)<n) break;//如果剩下的所有
21             if (s[depth] < s[depth - 1]) break;//因为要满足递增J又是倒着枚举的所以满足单调的性质 就可以直接break掉
22             dfs(depth+1);
23         }
24     }
25     return 0;
26 }
27 int main(){
28   ios::sync_with_stdio(false);
29     cin>>n;
30     s[1]=1;ans=1;
31     while(!dfs(2)) ++ans;
32 }

 

 

 

posted @ 2018-08-24 02:46  saionjisekai  阅读(430)  评论(1编辑  收藏  举报