标签:style blog color io os ar for sp 2014
题意
给出一串由D,I,?构成的长为n的字符串,这个字符串表示满足某种规则的1到n+1的排列集合,D表示该位置数字比前面一个小,I表示该位置的数字比前面一个大,?表示不确定可D可I
比如
满足DI的数字排列有3,1,2和2,1,3
1<=n<=1000,求有多少种满足此条件的字符串
设计的dp如下
dp[i][j] 代表满足上述字符串前i-1项的长为i尾巴为j的1到i的排列数目
当第i-1项为D时
dp[i][j]=sigma(dp[i-1][k]),i-1=>k>=j
当第i-1项为I时
dp[i][j]=sigma(dp[i-1][k]),j>k>=1
最后输出sigma(dp[n+1][k]),1<=k<=n+1
为什么是这样,原因是1到i-1的排列的后面一位写上j的时候,把前面i-1个数大于等于j的数都加1,便得到一个新的1到i的排列
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <string> using namespace std; #define LL long long const LL MOD=1000000007; char str[2222]; LL dp[1111][1111]; LL sum[1111][1111]; int main(){ #ifndef ONLINE_JUDGE freopen("H:/in.txt","r",stdin); #endif // ONLINE_JUDGE while(scanf("%s",str+2)!=EOF){ memset(dp,0,sizeof(dp)); memset(sum,0,sizeof(sum)); dp[1][1]=1; sum[1][1]=1; LL len=strlen(str+2); for(LL i=2;i<2+len;i++){ for(LL j=1;j<=i;j++){ if(str[i]=='D' || str[i]=='?'){ dp[i][j]+=sum[i-1][i-1]-sum[i-1][j-1]; dp[i][j]=(dp[i][j]+MOD)%MOD; } if(str[i]=='I' || str[i]=='?'){ dp[i][j]+=sum[i-1][j-1]; dp[i][j]=(dp[i][j]+MOD)%MOD; } sum[i][j]=(sum[i][j-1]+dp[i][j])%MOD; } } LL ans=0; for(LL i=1;i<=len+1;i++) ans=(ans+dp[len+1][i])%MOD; printf("%lld\n",ans); } return 0; }
ZOJ 3543 Number String 【2011大连区域赛】【dp】
标签:style blog color io os ar for sp 2014
原文地址:http://blog.csdn.net/u011775691/article/details/40381013