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
来源
题解:
要求不要出现“11”这样的子串,而0和1是反复重现,区别在于出现的位置,由而可以想到动态规划,当然正常的动态会超时,所以要记忆搜索。下面给出两个代码,一个原始的,一个优化的。原始的加以理解。
方法一:以0结尾的串,可以选择加“1”or“0”,而以1结尾的只能选择“0”了。
方法二:找出状态状态转移方程:d[i]=d[i-1]+d[i-2]。解释i为以0结尾的长度i的子串不含“11”的数量,给个数组对比看一下
d[0] | d[1] | d[2] | d[3] |
0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 |
0 | 1 | 0 | 0 |
1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 |
求长度为3的子串的答案,那必然是求尾部是0和1的和,尾部为1的话,那倒数第二个数必然是0,由此就可以得出以上的状态转移方程了。
方法三:实现理解不了法二的状态转移方程的话,建议可以把法一的思想改为状态转移方程。
dp[i][0]=dp[i-1][0]+dp[i-1][1];//以i长度0结尾的和=(i-1)长度的以1结尾+(i-1)长度的以0结尾
dp[i][1]=dp[i-1][0];//以i长度1结尾的=(i-1)长度的以0结尾
最后答案就是dp[i][0]+dp[i][1]
原创代码1:(超时)
#include<stdio.h>
int ans=0;
void f(char c,int d)
{
if(d==0)
{
ans++;
return ;
}
if(c=='0')
{
f('0',d-1);
f('1',d-1);
}
else
{
f('0',d-1);
}
}
int main()
{
int n,i,t;
scanf("%d",&n);
for(i=0;i<n;i++)
{
ans=0;
scanf("%d",&t);
f('0',t);
printf("%d\n",ans);
}
return 0;
}
原创代码2:
#include<stdio.h>
int main()
{
int n,i,t;
scanf("%d",&n);
int d[45];
d[0]=1;
d[1]=2;
for(i=2;i<=40;i++)
d[i]=d[i-1]+d[i-2];
for(i=0;i<n;i++)
{
scanf("%d",&t);
printf("%d\n",d[t]);
}
return 0;
}