動態規劃-線性dp-hdu-4055

http://www.javashuo.com/article/p-gjwhuanu-ew.htmlphp

這道題是大連的某一年的現場賽的題hdu-4055
,,,剛開始作線性dp的題,,看了好半天才看懂解法,,html

分析

參考1
參考2ios

題目的意思就是給出一個僅有1~n組成的序列的關係s:'I'表示 \(a[i+1]>a[i]\),'D'表示 \(a[i+1] < a[i]\),,'?'表示均可以,,而後問你全部可能的狀況的總數,,c++

\(dp[i][j]\) 表示長度爲i而且僅由1~i組成的序列以j結尾時的種類數,,spa

  • \(s[i]= ?\) 時,,當前點的可能狀況就是前面全部狀況的和,即 \(dp[i][j]=\sum_{k=1}^{i-1}dp[i-1][k]\).net

  • \(s[i]=I\) 時,,由於第i位固定就爲j了,而且前一位要知足小於等於j,因此就要找出全部長度爲i-1且結尾小於等於j-1的狀況的和,,即: \(dp[i][j]=\sum_{k=1}^{j-1}dp[i-1][k]\)code

  • \(s[i]=D\) 時,,和等於I的狀況相反,,也就是要找到全部長度爲i-1且最後一位大於j的種類數(同時要小於i-1),,也就是說能夠直接用?的種類數減去I的種類數,,即: \(dp[i][j]=\sum_{k=j}^{i-1}dp[i-1][k]=\sum_{k=1}^{i-1}dp[i-1][k]-\sum_{k=1}^{j-1}dp[i][k]\)htm

假定每次使第i位爲j時,前面大於等於j的值都加一,,這樣保證前i個數都出現一次,,同時i-1變成了i,,j變成了j+1,,j就放在了後面,,因此遍歷中的k是從j~i-1,,,blog

參考ci

最後用前綴和維護一下那個和,空間換時間

代碼

//hdu
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string.h>
#include <algorithm>
#include <queue>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;//1061109567
const ll linf = 0x3f3f3f3f3f3f3f;
const double eps = 1e-6;
const double pi = 3.14159265358979;
const int maxn = 1e3 + 5;
const int maxm = 2e5 + 5;
const ll mod = 1e9 + 7;
int dp[maxn][maxn], sum[maxn][maxn];
char s[maxn];
int main()
{
//    freopen("233.in" , "r" , stdin);
//    freopen("233.out" , "w" , stdout);
//    ios_base::sync_with_stdio(0);
//    cin.tie(0);cout.tie(0);
    while(~scanf("%s", s + 2))
    {
        int len = strlen(s + 2);
        memset(dp, 0, sizeof dp);
        memset(sum, 0, sizeof sum);
        dp[1][1] = sum[1][1] = 1;
        for(int i = 2; i <= len + 1; ++i)
        {
            for(int j = 1; j <= i; ++j)
            {
                if(s[i] == 'I')
                    dp[i][j] = sum[i - 1][j - 1];
                if(s[i] == 'D')
                    dp[i][j] = (sum[i - 1][i - 1] - sum[i - 1][j - 1] + mod) % mod;
                if(s[i] == '?')
                    dp[i][j] = sum[i - 1][i - 1];
                sum[i][j] = (dp[i][j] + sum[i][j - 1]) % mod;
            }
        }
        printf("%d\n", sum[len + 1][len + 1]);
    }
    return 0;
}

(end)

相關文章
相關標籤/搜索