zoukankan      html  css  js  c++  java
  • 暑假考试题8:mine(dp)

    题目:

     分析:

    这个数据范围只能做线性递推或加一个log。而这道题要求方案数,很容易联想到dp。主要是dp的转移情况多且复杂。

    特别要考虑1,因为可能是1的前面或后面有*,于是就将1的情况一分为二:前面的1和后面的1(指的是*1的前面还是后面)

    考虑每一位能够由前一位的哪些状态转移过来:

    0:   前1和0

    前1:  *

    后1:   0 和 前1

    * :   后1 和 2 和 *

    2: *

    :前面转移的都可以转移一遍,因为这一位可以填很多种

    然后设dp[ i ] [ 0/1/2/3 ] [ 0/1 ]为递推到第i位,这一位填0或1或*或2 的方案数,最后一维0表示前1,1表示后1。

    注意初始化和输出。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define N 1000005
    const ll mod=1e9+7;
    ll dp[N][5][3];
    char s[N];
    int main()
    {
        freopen("mine.in","r",stdin);
        freopen("mine.out","w",stdout);
        scanf("%s",s+1);
        int len=strlen(s+1);
        if(s[1]=='?') dp[1][0][0]=1,dp[1][2][0]=1,dp[1][1][1]=1;
        else if(s[1]=='0') dp[1][0][0]=1;
        else if(s[1]=='*') dp[1][2][0]=1;
        else if(s[1]=='1') dp[1][1][1]=1;
        //2->*
        for(int i=2;i<=len;i++)
        if(s[i]=='0'){
            dp[i][0][0]=(dp[i-1][0][0]+dp[i-1][1][0])%mod;
        }
        else if(s[i]=='1'){
            dp[i][1][0]=dp[i-1][2][0];
            dp[i][1][1]=(dp[i-1][0][0]+dp[i-1][1][0])%mod;//
        }
        else if(s[i]=='2'){
            dp[i][3][0]=dp[i-1][2][0];
        }
        else if(s[i]=='*'){
            dp[i][2][0]=(dp[i-1][2][0]+dp[i-1][1][1]+dp[i-1][3][0])%mod;//
        }
        else if(s[i]=='?'){
            dp[i][0][0]=(dp[i-1][1][0]+dp[i-1][0][0])%mod;
            dp[i][1][0]=dp[i-1][2][0]; dp[i][1][1]=(dp[i-1][1][0]+dp[i-1][0][0])%mod;//
            dp[i][2][0]=(dp[i-1][2][0]+dp[i-1][1][1]+dp[i-1][3][0])%mod;//+dp[i-1][3][0]
            dp[i][3][0]=dp[i-1][2][0];
        }
        if(s[len]=='?')
         printf("%lld
    ",(dp[len][0][0]+dp[len][1][0]+dp[len][2][0])%mod);
        else if(s[len]=='0')
         printf("%lld
    ",dp[len][0][0]);
        else if(s[len]=='1')
         printf("%lld
    ",dp[len][1][0]);
        else if(s[len]=='*')
         printf("%lld
    ",dp[len][2][0]);
        else printf("0
    ");
        return 0;
    }
    /*
    ?1?
    1??1
    *2*??
    ???
    ??
    0?*?*100???*2??0???
    0?*?*100???*2*?0???
    */
  • 相关阅读:
    《C++ 并发编程》- 第1章 你好,C++的并发世界
    30分钟,让你成为一个更好的程序员
    程序员技术练级攻略
    谈新技术学习方法-如何学习一门新技术新编程语言
    计算机科学中最重要的32个算法
    程序员学习能力提升三要素
    一位在MIT教数学的老师总结了十条经验
    学习算法之路
    十个顶级的C语言资源助你成为优秀的程序员
    Linux中LoadAverage分析
  • 原文地址:https://www.cnblogs.com/mowanying/p/11436660.html
Copyright © 2011-2022 走看看