您的位置:首页 > 其它

hdu 4055 Number String

2013-10-04 10:13 302 查看
题意:给出一个字符串,问1~n这n个数中有多少种排列满足给定字符串的要求,字符串str[i]=='I'代表第i位数字要比它前一位大,str[i]=='D'代表第i位数字要比它前一位小,str[i]=='?'代表第i位数字任意。

思路:刚开始没想出怎么做,看了看题解,感觉大体思路还是能看懂的,但是细节的地方怎么也没看明白,我理解能力是有多差Orz……后来没办法了,自己YY过了,果然还是自己想的思路好写。我的思路是这样的:在1~n中拿走任意一个数,剩下的数其实可以重新编号(1~n-1),所以每一次选的时候也可以看成是一个1~k(k是当前剩下的数)的数选一个。这样的话,第i次选的数就取决于第i-1次选的数在它剩下的数中的位置了。用dp[i][j]表示到第i位时,在剩下的数中选第j个数的排列的个数。这样的话状态转移方程很容易就能列出来:如果str[i]=='I',dp[i][j]=sum{dp[i-1][1]~dp[i-1][j]},如果str[i]=='D',dp[i][j]=sum{dp[i-1][j+1]~dp[i-1][k]}(k是到i-1位时剩余的数)。这题数组开long
long 的话居然会超时,这数据……不能多说。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=1000+10;
const int mod=1000000007;
char str[maxn];
int dp[maxn][maxn],sum[maxn][maxn];
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    while(~scanf("%s",str))
    {
        n=strlen(str);
        n++;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;++i) sum[i][0]=0;
        for(int i=1;i<=n;++i)
        {
            dp[1][i]=1;
            sum[1][i]=i;
        }
        for(int i=2;i<=n;++i)
        {
            for(int j=1;j<=n-i+1;++j)
            {
                if(str[i-2]=='I'||str[i-2]=='?')
                  dp[i][j]+=sum[i-1][j]-sum[i-1][0];
                if(str[i-2]=='D'||str[i-2]=='?')
                  dp[i][j]+=sum[i-1][n-i+2]-sum[i-1][j];
                dp[i][j]%=mod;
                sum[i][j]=(sum[i][j-1]+dp[i][j])%mod;
            }
        }
        int res=(dp
[1]+mod)%mod;
        printf("%d\n",res);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: