HDU 3485【101】 51nod 1668【010】 joj 2171【111】动态规划

有一个只含0和1的长度为n的串,问不含有101的所有串的个数。

——不存在连续的101、010、111的字符串数量

HDU:https://cn.vjudge.net/problem/HDU-3485

 

51nod:

https://blog.csdn.net/Viscu/article/details/52669071

https://blog.csdn.net/lwlldd/article/details/70941554

https://blog.csdn.net/xtulollipop/article/details/52689159

https://blog.csdn.net/f_zyj/article/details/52663012

https://blog.csdn.net/LuRiCheng/article/details/52673193

 

JOJ:https://blog.csdn.net/kongming_acm/article/details/5377198

https://blog.csdn.net/jcwkyl/article/details/4153057

http://blog.sina.com.cn/s/blog_944759ba0100vmz9.html

 


 

记录后两位,共有4种情况

00->0

01->1

10->2

11->3;

【101的时候】

dp[i][0]=dp[i-1][0]+dp[i-1][2];
dp[i][1]=dp[i-1][0];
dp[i][2]=dp[i-1][1]+dp[i-1][3];
dp[i][3]=dp[i-1][1]+dp[i-1][3];

 

 

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define mp make_pair
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,x,n) for(int i=(x); i<=(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
#define mod 9997
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const ULL base = 100000007;//33951943
const int INF = 0x3f3f3f3f;
const ll LNF = 9997;
const int maxn = 10000+20;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/*
010
00 - 0
01 - 1
10 - 2
11 - 3
*/

ll dp[maxn][4],ans[maxn];
void init()
{
    //111
    ms(dp,0);
    dp[1][0]=2;
    dp[2][0]=1;dp[2][1]=1;dp[2][2]=1;dp[2][3]=1;
    for(int i=3;i<10000;i++)
    {
        dp[i][0]=(dp[i-1][0]+dp[i-1][2])%mod;
        dp[i][1]=(dp[i-1][0]+dp[i-1][2])%mod;
        dp[i][2]=(dp[i-1][1]+dp[i-1][3])%mod;
        dp[i][3]=(dp[i-1][1])%mod;
    }
}
void init1()
{
    //101
    ms(dp,0);
    dp[1][0]=2;
    dp[2][0]=1;dp[2][1]=1;dp[2][2]=1;dp[2][3]=1;
    for(int i=3;i<10000;i++)
    {
        dp[i][0]=(dp[i-1][0]+dp[i-1][2])%mod;
        dp[i][1]=(dp[i-1][0])%mod;
        dp[i][2]=(dp[i-1][1]+dp[i-1][3])%mod;
        dp[i][3]=(dp[i-1][1]+dp[i-1][3])%mod;
    }
}


void init2()
{
    //010
    ms(dp,0);
    dp[1][0]=2;
    dp[2][0]=1;dp[2][1]=1;dp[2][2]=1;dp[2][3]=1;
    for(int i=3;i<10000;i++)
    {
        dp[i][0]=(dp[i-1][0]+dp[i-1][2])%mod;
        dp[i][1]=(dp[i-1][0]+dp[i-1][2])%mod;
        dp[i][2]=(dp[i-1][3])%mod;
        dp[i][3]=(dp[i-1][1]+dp[i-1][3])%mod;
    }
}
int main()
{
    int n;
    while(cin>>n)
    {
        init();
        if(n==-1) break;
        cout<<(dp[n][0]+dp[n][1]+dp[n][2]+dp[n][3])%mod<<endl;
    }
}
/*
【题意】

【类型】

【分析】

【时间复杂度&&优化】

【trick】
首先dp打表找个规律:
如何DP?
这里我们找合法串:010
假设末尾i是1,那么i-1位置上无论是0和还是1都合法,不会出现010的情况,那么
就是dp[i][1] = dp[i-1][0] + dp[i-1][1];
如果末尾i是0,
如果i-1位置上是0,那么无论如何也是合法的,
如果i-1的位置上是1,会出现010/101这样的情况,那么讨论第i-2位上的,i-2如果是0,那么会出现010的情况,

如果i-2位置上是1的话,无论如何都是合法串,那就是dp[i][0] = dp[i-1][0] + dp[i-2][1];
【数据】
0 1(i-3)-0
00 01 10 11(i-2)x1
000 001 【010/1】 011 100 【110/1】 111 (i-1) x10
010-1
110-1

*/
01字符串递推DP

 

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define mp make_pair
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,x,n) for(int i=(x); i<=(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
#define mod 9997
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const ULL base = 100000007;//33951943
const int INF = 0x3f3f3f3f;
const ll LNF = 9997;
const int maxn = 10000+20;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/*
0
001
0 1
00 01 10 11
0 2 4 7
*/

ll dp[maxn][2],ans[maxn];
void init()
{
    ms(dp,0);
    ms(ans,0);
    ans[0]=0;ans[1]=2;ans[2]=4;
    dp[1][0]=1,dp[1][1]=1;
    dp[2][0]=2,dp[2][1]=2;
    //dp[3][0]=4;dp[3][1]=3;
    for(int i=3;i<10000;i++)
    {
        dp[i][0]=(dp[i-1][0]+dp[i-1][1])%mod;
        dp[i][1]=(dp[i-1][1]+dp[i-2][0])%mod;
        ans[i]=(dp[i][0]%mod+dp[i][1]%mod)%mod;
    }
}
int main()
{
    int n;
    while(cin>>n)
    {
        init();
        if(n==-1) break;
        cout<<ans[n]%mod<<endl;
    }
}
/*
【题意】

【类型】

【分析】

【时间复杂度&&优化】

【trick】
首先dp打表找个规律:
如何DP?
这里我们找合法串:010
假设末尾i是1,那么i-1位置上无论是0和还是1都合法,不会出现010的情况,那么
就是dp[i][1] = dp[i-1][0] + dp[i-1][1];
如果末尾i是0,
如果i-1位置上是0,那么无论如何也是合法的,
如果i-1的位置上是1,会出现010/101这样的情况,那么讨论第i-2位上的,i-2如果是0,那么会出现010的情况,

如果i-2位置上是1的话,无论如何都是合法串,那就是dp[i][0] = dp[i-1][0] + dp[i-2][1];
【数据】
0 1(i-3)-0
00 01 10 11(i-2)x1
000 001 【010/1】 011 100 【110/1】 111 (i-1) x10
010-1
110-1

*/
dp[i][j]:长度i,j代表末尾0 or 1

 

转载于:https://www.cnblogs.com/Roni-i/p/9489114.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值