hdu 4055 Number String(排列dp)

题目链接:hdu 4055 Number String

题意:

给你一个长度为n的指定的升降序列,问有多少种排列,符合这样的序列。

题解:

训练赛的时候没想出来,大概这种排列的dp需要转换一下思维吧。

考虑dp[i][j]表示前i个数只用1~i,结尾为j。

然后就有

如果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]。

如果s[i - 1]是‘?’,那么dp[i][j] = dp[i-1][i-1] + ... + dp[i-1][1]。

比较巧妙。需要好好想想,详细题解:传送门

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 3 using namespace std;
 4 #define mst(a,b) memset(a,b,sizeof(a))
 5 
 6 const int N=1007,P=1e9+7;
 7 char s[N];
 8 int dp[2][N],n,x;
 9 
10 void up(int &a,int b){a+=b;if(a>=P)a-=P;}
11 
12 int main(){
13     while(~scanf("%s",s+1))
14     {
15         n=strlen(s+1)+1;
16         mst(dp,0),dp[x=0][1]=1;
17         F(i,2,n)
18         {
19             x^=1,mst(dp[x],0);
20             if(s[i-1]=='?')
21             {
22                 F(j,1,i-1)up(dp[x][1],dp[x^1][j]);
23                 F(j,2,i)up(dp[x][j],dp[x][1]);
24             }
25             else if(s[i-1]=='I')
26             {
27                 F(j,1,i)up(dp[x][j],dp[x][j-1]+dp[x^1][j-1]);
28             }
29             else
30             {
31                 for(int j=i;j;j--)
32                     up(dp[x][j],dp[x][j+1]+dp[x^1][j]);
33             }
34         }
35         int ans=0;
36         F(i,1,n)up(ans,dp[x][i]);
37         printf("%d\n",ans);
38     }
39     return 0;
40 }
View Code

 

posted @ 2017-10-02 19:21  bin_gege  阅读(143)  评论(0编辑  收藏  举报