「火」皇家烈焰

「火」皇家烈焰

https://ac.nowcoder.com/acm/problem/53683

这是一道动态规划的题。

题意:给出一个长度为n的字符串,n最大1000000。 每个字符代表一种特殊含义。

0:这个格子没有烈焰,且其左右两个格子均没有烈焰
1:这个格子没有烈焰,且其左右两个格子中只有一个烈焰
2:这个格子没有烈焰,且其左右两个格子中均有烈焰
*:这个格子有烈焰
?:未告诉你本格情况

求所有的方案数

分析: 可以发现,第i位方案数,和前一位和后一位有关系。 前一位可以通过转移方程来解决,所以还剩下当前位i、当前位i是否有火、i+1位是否有火。

所以我们需要一个三维数组来表示dp

dp[i][0/1][0/1]

i:表示第i位
第一个[0/1]: 表示第i位有没有火,有火就用1来表示,没火就用0来表示
第二个[0/1]: 表示第i+1位有没有火,有火就用1来表示,没火就用0来表示

然后初始化dp[0][0][0],dp[0][0][1] 的方案数位1 。这是显然的。

1、当字符为0的时候,代表这个格子没有烈焰,且其左右两个格子均没有烈焰。
所以 dp[i][0][0]+=dp[i-1][0][0]

2、当字符为1的时候,代表这个格子没有烈焰,且其左右两个格子中只有一个烈焰。
所以我们就可以分2中情况讨论,第一种就是左边格子有火焰 :dp[i][0][0]+=dp[i-1][1][0]
第二种就是右边格子有火焰 :dp[i][0][1]+=dp[i-1][0][0]
.......

最后答案就是 dp[n][0][0]+dp[n][1][0]。

剩下的情况大家自己去分类讨论下。

最后注意要开long long。不要忘记取mod。

AC代码: (供参考)

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <cctype>
#include <cmath>
#include <cassert>

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define INF 0x3f3f3f3f
#define PI 3.14159265358979323846

using namespace std;

typedef long long ll;

const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

const int N=1000000+100;

char s[N];

ll dp[N][2][2];//  dp[i][0/1][0/1] 表示当前第i位有没有火焰和第i+1位有没有火焰 

int main()
{
    scanf("%s",s+1);
    int len=strlen(s+1);
    dp[0][0][0]=dp[0][0][1]=1;
    for(int i=1;i<=len;i++)
    {
        if(s[i]=='0')
        {//表示第i位没有火焰,并且左右都没有火焰 
            dp[i][0][0]+=dp[i-1][0][0];  
            dp[i][0][0]%=mod;
        }
        else if(s[i]=='1')
        {
            dp[i][0][1]+=dp[i-1][0][0];
            dp[i][0][1]%=mod;

            dp[i][0][0]+=dp[i-1][1][0];
            dp[i][0][0]%=mod;
        }
        else if(s[i]=='2')
        {
            dp[i][0][1]+=dp[i-1][1][0];
            dp[i][0][1]%=mod;
        }
        else if(s[i]=='*')
        {
            dp[i][1][0]+=dp[i-1][1][1];
            dp[i][1][0]%=mod;

            dp[i][1][0]+=dp[i-1][0][1];
            dp[i][1][0]%=mod;

            dp[i][1][1]+=dp[i-1][1][1];
            dp[i][1][1]%=mod;

            dp[i][1][1]+=dp[i-1][0][1];
            dp[i][1][1]%=mod;
        }
        else
        {
            dp[i][0][0]+=dp[i-1][0][0];  
            dp[i][0][0]%=mod;
            //-------------------------------

            dp[i][0][1]+=dp[i-1][0][0];
            dp[i][0][1]%=mod;

            dp[i][0][0]+=dp[i-1][1][0];
            dp[i][0][0]%=mod;

            //-------------------------------

            dp[i][0][1]+=dp[i-1][1][0];
            dp[i][0][1]%=mod;

            //-------------------------------

            dp[i][1][0]+=dp[i-1][1][1];
            dp[i][1][0]%=mod;

            dp[i][1][0]+=dp[i-1][0][1];
            dp[i][1][0]%=mod;

            dp[i][1][1]+=dp[i-1][1][1];
            dp[i][1][1]%=mod;

            dp[i][1][1]+=dp[i-1][0][1];
            dp[i][1][1]%=mod;
        }
    } 
    printf("%lld\n",(dp[len][0][0]+dp[len][1][0])%mod);
    return 0;
}
全部评论

相关推荐

11-11 14:21
西京学院 C++
Java抽象练习生:教育背景放最前面,不要耍小聪明
点赞 评论 收藏
分享
头像
11-06 10:58
已编辑
门头沟学院 嵌入式工程师
双非25想找富婆不想打工:哦,这该死的伦敦腔,我敢打赌,你简直是个天才,如果我有offer的话,我一定用offer狠狠的打在你的脸上
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务