首页 > 代码库 > ZOJ 3543 Number String 【2011大连区域赛】【dp】
ZOJ 3543 Number String 【2011大连区域赛】【dp】
题意
给出一串由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】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。