input:
3
4
10
20
-1
output:
7
12
351
97229
思路:
这道题真的没啥思路,一开始想用排列组合的办法的,结果死活想不出来,可能是太久没接触dp了+眼瞎,完全没有往这个方向去想,实在是卡了太久了,所以就借鉴了一下度娘上别人的想法。看了蛮多思路的,但是可能因为我理解能力有点差,所以看了很多想法,才慢慢把这个想清楚。我会努力在这里把思路讲清楚(毕竟这也能证明,我真的想清楚了)
先补充一下dp吧
我个人理解的dp是,要实现某个目的可以分成很多步骤,但每个步骤之间都有联系,需要前面的铺垫才能进行下一步(类似造楼房,没有一二两层也不可能会有第三层
本题的dp:
先定义cnt[n]为长度为n的不包含101的数组,数组的值为长度为n的不包含101的数组的个数。
对任何不包含101的字符串在最后面加0,都依旧是不含101的,因此
如果有长度为n的不含101的字符串且最后一个数字是0,可以确定它的个数为cnt[n-1](这一点真的尤其重要,可能需要好好体会一下,一开始我就是这里出了问题,然后怎么也想不明白)
现在问题就转化成了长度为n的不含101的字符串且最后一个数字是1的个数该怎么计算(理一下思路):
1.不看结尾,长度为n-1的不含101的字符串的个数为cnt[n-1];
2.考虑长度为n-1的不含101的字符串的末尾的2位数字:
10不可行,00可行
11可行,01也可行
所以需要减去的就是长度为n-1的不含101的字符串的末尾为10的情况
即长度为n-2的不含101的字符串且末尾为0的个数-长度为n-3的不含101的字符串且末尾为0的个数->cnt[n-2]-cnt[n-3]
3.最终结果:
长度为n的不含101的字符串且最后一个数字是1的个数:
cnt[n-1]-cnt[n-2]-cnt[n-3]
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int a[111]={
0,2,4,7};
int n;
int main()
{
for(int i=4;i<=20;i++) a[i]=2*a[i-1]-a[i-2]+a[i-3];while(cin >> n){
if(n==-1) break;else cout<<a[n]<<endl;}return 0;
}