Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2007 Accepted Submission(s):
973
/* dp方程的设定比较显然,dp[i][j]表示选了i个元素,最后一个是j的方案数。 但是在状态转移的时候,我们不得不考虑前面选了什么,也就是状态的设定是有后效性的, 所以考虑给状态再添一层含义:必须选前i个元素。 那么这样岂不是每次只能选i吗?那么第二维岂不是没有用了? 所以我们考虑用j把i替换出来,那么在状态转移的时候就需要考虑放入i时,怎么替换能使原来的大小顺序保持不变。 将dp[i-1][j]的i-1个数的序列中 ≥j 的数都加1,这样i-1变成了i,j变成了j+1,而j自然就补在后面了。 处理I:dp[i][j] = Σdp[i-1][x],其中1≤x≤j-1,可进一步简化,dp[i][j] = dp[i][j-1]+dp[i-1][j-1] 处理D:dp[i][j] = Σdp[i-1][x],其中j≤x≤i-1,可进一步简化,dp[i][j] = dp[i-1][j+1]+dp[i-1][j] 处理?:dp[i][j] = Σdp[i-1][x],其中1≤x≤i-1 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 1010 #define mod 1000000007 char s[maxn]; int dp[maxn][maxn]; int main(){ while(scanf("%s",s+1)!=EOF){ int n=strlen(s+1);n++; int ans=0; memset(dp,0,sizeof(dp)); dp[1][1]=1; for(int i=2;i<=n;i++){ if(s[i-1]==‘I‘) for(int j=2;j<=i;j++) dp[i][j]=(dp[i][j-1]+dp[i-1][j-1])%mod; else if(s[i-1]==‘D‘) for(int j=i-1;j>=1;j--) dp[i][j]=(dp[i][j+1]+dp[i-1][j])%mod; else { int sum=0; for(int j=1;j<i;j++)sum=(sum+dp[i-1][j])%mod; for(int j=1;j<=i;j++)dp[i][j]=sum; } } for(int i=1;i<=n;i++)ans=(ans+dp[n][i])%mod; printf("%d\n",ans); } }
原文:http://www.cnblogs.com/thmyl/p/6962980.html