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组测试数据;
【分析】
开始考虑使用dfs,搜索所有可能情况,发现两个'1'相连时说明不合题意。不过考虑到数据规模(2<=m<=40),搜索会超时。因此考虑从简单的情况入手推理:
m=2时,有00 01 10三种情况
m=3时,有000 001 010 100 101五种情况
m=4时,有0000 0001 0010 0100 0101 1000 1001 1010八种情况
……
可归纳推理得m=x时情况数为 m=x-1和m=x-2时的情况数之和。
故可以考虑使用dp求解:设dp[i]为长度为i的01字符串中不含"11"子串的字符串数。需要分两种情况讨论:
(1)第i位为‘0’时,情况数为dp[i-1]
(2)第i位为‘1’时,注意第i-1位必为‘0’,因此情况数为dp[i-2]。
不难发现,这是一个“斐波那契数列”模型(此模型在dp情景中经常出现)。
#include <stdio.h>
#include <string.h>
#define maxn 45
int n,m;
int dp[maxn];
void getAns(int *dp)
{
int i;
dp[2]=3,dp[3]=5;
for(i=4;i<maxn;i++)
dp[i]=dp[i-1]+dp[i-2];
}
int main()
{
int i;
getAns(dp);
scanf("%d",&n);
while(n--)
{
scanf("%d",&m);
printf("%d\n",dp[m]);
}
return 0;
}
附:dfs解法(超时)
#include <stdio.h>
#include <string.h>
#define maxn 45
int n,m;
int ans;
char str[maxn];
void dfs(int cur)
{
int i;
if(cur==m)
{
ans++;
//printf("%s\n",str);
return;
}
for(i=0;i<2;i++)
{
if(i==1 && str[cur-1]=='1')
continue;
str[cur]=i+'0';
dfs(cur+1);
}
}
int main()
{
int i;
scanf("%d",&n);
while(n--)
{
scanf("%d",&m);
ans=0;
dfs(0);
printf("%d\n",ans);
}
return 0;
}