[HDU 4055] Number String

DP经典好题。。。

题意简述:

给定一个字符串由'I' 'D' '?'组成,长度为n,表示1-n+1个数任意排列满足字符串给出的限定条件,I表示第i位到第i+1位是上升的,D表示是下降的,?表示都可以,问有多少种排列满足给出的条件,答案要%一个mod值1e9+7

思路浅析:

设dp[ i ] [ j ] 表示前 i 个满足字符串条件结尾为 j 的i的排列

  1. 若s[i] == 'I', dp[ i ] [ j ] = dp[ i - 1 ] [ j - 1 ] + dp[ i - 1 ] [ j - 2 ] +...+ dp[ i - 1 ] [ 1 ]

  2. 若s[i] == 'D', dp[ i ] [ j ] = dp [ i - 1 ] [ j ] + dp[ i ] [ j + 1 ] +...+ dp[ i - 1 ] [ i ]

若下一步是下降的,那么因为要令当前位为j,如果前面出现过j,就令前面的所有大于等于j的数+1,就能构造出新的排列了。比如

{1, 3, 5, 2, 4},要在第六位插入3,令 >= 3的数都+1,于是就构造出新的 排列{1, 4, 6, 2, 5, 3}。然后代码的话处理出前缀和sum[i][j],就不用dp[i][j]了

code:

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int mod = 1e9 + 7;
const int N = 1010;

int sum[N][N];
char s[N];

main()
{
    // freopen("in.txt", "r", stdin);
    while (scanf("%s", s) != -1)
    {
        sum[0][1] = 1;
        int n = strlen(s);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n + 1; j++)
            {
                sum[i][j] = sum[i][j - 1];
                if (s[i - 1] != 'D')
                    sum[i][j] += sum[i - 1][j - 1];
                if (s[i - 1] != 'I')
                    sum[i][j] += (sum[i - 1][i] - sum[i - 1][j - 1] + mod);
                sum[i][j] %= mod;
            }
        std::cout << sum[n][n + 1] << '\n';
    }
    return 0;
}
上一篇:【Codeforces Round 725】Canada Cup 2016


下一篇:洛谷P3370 && 字符串哈希讲解