dp D. Caesar's Legions

https://codeforces.com/problemset/problem/118/D

 

这个题目有点思路,转移方程写错了。

这个题目看到数据范围之后发现很好dp,

dp[i][j][k1][k2]代表的是前面i个1 j 个0,到第 i+j 为有连续 k1 个 1,连续 k2 个0形成排列的方案数。

这个要注意其中k1 k2一定有一个是0

状态转移方程 dp[i+1][j][k1+1][0]+=dp[i][j][k1][k2]   dp[i][j+1][0][k2+1]+=dp[i][j][k1][k2]

如果k1==0 那么就会从很多状态转移过来

但是如果k1!=0就只会从k1这个状态转移过来。

这个就是这个状态转移方程为什么这么写的原因。

 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#define inf 0x3f3f3f3f
#define debug(x) cout<<"-----"<<" x = "<<x<<"-----"<<endl
using namespace std;
const int  mod = 1e8;
const int maxn = 1e5 + 10;
int dp[110][110][12][12];

int main()
{
    int n1, n2, k1, k2;
    scanf("%d%d%d%d", &n1, &n2, &k1, &k2);
    memset(dp, 0, sizeof(dp));
    int ans = 0;
    dp[0][0][0][0] = 1;
    for(int i=0;i<=n1;i++)
    {
        for(int j=0;j<=n2;j++)
        {
            for(int l=0;l<=k1;l++)
            {
                for(int r=0;r<=k2;r++)
                {
                    if(i!=n1&&l!=k1)
                    {
                        dp[i + 1][j][l + 1][0] += dp[i][j][l][r];
                        dp[i + 1][j][l + 1][0] %= mod;
                    }
                    if(j!=n2&&r!=k2)
                    {
                        dp[i][j + 1][0][r + 1] += dp[i][j][l][r];
                        dp[i][j + 1][0][r + 1] %= mod;
                    }
                }
            }
        }
    }
    for (int i = 0; i <= k1; i++)
    {
        ans += dp[n1][n2][i][0];
        ans %= mod;
    }
    for(int i=0;i<=k2;i++)
    {
        ans += dp[n1][n2][0][i];
        ans %= mod;
    }
    printf("%d\n", ans);
    return 0;
}

 

posted @ 2019-05-21 16:04  EchoZQN  阅读(137)  评论(0编辑  收藏  举报