HDU 4055 Number String(不错的DP题)

题意:

给你一个字符串s,s[i] = 'D'表示排列中a[i] > a[i+1],s[i] = 'I'表示排列中a[i] < a[i+1]。

比如排列 {3, 1, 2, 7, 4, 6, 5} 表示为字符串 DIIDID。


解题思路:

很巧妙的DP做法,dp[i][j]表示前i个满足字符串条件的结尾为j的 i 的排列,注意是i的排列,前面并没有数大于i。那又是如何往下递推呢?

如果s[i - 1]是' I ',那么dp[i][j] = dp[i-1][j-1] + dp[i-1][j-2] + .. + dp[i-1][1]

如果s[i - 1]是‘D’,那么dp[i][j] = dp[i-1][j] + dp[i-1][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]了。感觉还是很巧妙的,好题!


/* **********************************************
Author      : JayYe
Created Time: 2013/10/6 23:22:51
File Name   : Orz.cpp
*********************************************** */

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef __int64 ll;

const int maxn = 1000 + 5;
const int mod = 1000000007;

ll sum[maxn][maxn];
char s[maxn];

int main() {
    while(scanf("%s", s) != -1) {
        int len = strlen(s);
        sum[0][1] = 1;
        for(int i = 1;i <= len; i++) {
            for(int j = 1;j <= i+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;
            }
        }
        printf("%I64d\n", sum[len][len+1]);
    }
    return 0;
}


  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值