01串
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
2
-
描述
-
ACM的zyc在研究01串,他知道某一01串的长度,但他想知道不含有“11”子串的这种长度的01串共有多少个,他希望你能帮帮他。
注:01串的长度为2时,有3种:00,01,10。
-
输入
-
第一行有一个整数n(0<n<=100),表示有n组测试数据;
随后有n行,每行有一个整数m(2<=m<=40),表示01串的长度;
输出
- 输出不含有“11”子串的这种长度的01串共有多少个,占一行。 样例输入
-
2 2 3
样例输出
-
3 5
-
第一行有一个整数n(0<n<=100),表示有n组测试数据;
动态规划题,先找规律,尽量构成dp[i]和dp[i+n]的关系,然后就好解决了。
第一种方法:比较容易找规律就可以得到递推式
n==2的时候 00 01 10三种
n==3的时候 000 001 010 100 101 五种n==4的时候 n==3的时候的情况末尾都加0 五种 + n==2的时候情况末尾加0再加1 三种 = 八种
n==3的时候末尾不管是什么都可加0得到n==4的情况,而n==3的时候,末尾是0的还可以通过加1获得n==4的情况,而n==3时末尾是0的情况都是n==2的时候的所有情况通过末尾加0获得的,所以ans[i] = ans[i-1]+ans[i-2]
#include <cstdio>
#include <iostream>
using namespace std;
int fun(int m)
{
int ans[m+1];
for(int i=2; i<=m; i++)
{
if(i==2)
ans[i]=3;
else if(i==3)
ans[i]=5;
else
ans[i]=ans[i-1]+ans[i-2];
}
return ans[m];
}
int main()
{
int n;
cin>>n;
while(n--)
{
int m;
cin>>m;
cout<<fun(m)<<endl;
}
return 0;
}
第二种方法其实更加通用:
用dp[i][2]来记录第i位上0,1数字的个数分别为多少。
我们可以很容易知道:
dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
dp[i][1] = dp[i - 1][0];
所以我们就可以通过这种方式推出dp[m][0]+dp[m][1]
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int dp[41][2];
int main(){
int n;
scanf("%d", &n);
while(n--){
int m;
scanf("%d", &m);
memset(dp, 0, sizeof(dp));
dp[1][0] = 1;
dp[1][1] = 1;
for(int i=2; i<=m; i++){
dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
dp[i][1] = dp[i - 1][0];
}
printf("%d\n", dp[m][0]+dp[m][1]);
}
return 0;
}