計數dp-hdu-4054-Number String
阿新 • • 發佈:2019-01-24
題目連結:
題目大意:
給一個只含‘I','D','?'三種字元的字串,I表示當前數字大於前面的數字,D表示當前的數字小於前面一位的數字,?表示當前位既可以小於又可以大於。
問1~n的排列中有多少個滿足該字串。
解題思路:
計數dp.
dp[i][j]表示長度為i字串,最後一個數為j時,能達到滿足給定字串的1~i+1的排列個數。
轉移方程:
當S[i]='I'時,當前如果為j的話,前面的一位肯定要小於j,dp[i][j]+=Mi[j-1] ; //Mi[i]表示前面一位下標小於等於i dp[][1~i]的和
當S[i]='D'時,dp[i][j]+=(la-Mi[j-1]); //前一位要大於等於j
當S[i]='?'時,dp[i][j]+=la; //la表示前一位所有的狀態總和.
注意遞推的時候,前i位只和相對大小有關,與絕對大小無關,所以都用1~i表示,當增加一位時,就變成了1~i+1,如果當前為j,前面的小於j的狀態不變,大於等於j的狀態k所表示的值 現在表示k+1的值,這樣就從1~i等價的轉化成了1~i+1,這樣考慮就不用考慮1~n的放法了,遞推到n位時肯定都是1~n了。
程式碼:
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<cctype> #include<map> #include<vector> #include<set> #include<queue> #include<string> using namespace std; const int INF = 0x3f3f3f3f; const double eps = 1e-6; const double PI = acos(-1.0); typedef __int64 ll; //#pragma comment(linker, "/STACK:1024000000,1024000000") /* freopen("data.in","r",stdin); freopen("data.out","w",stdout); */ #define M 1000000007 #define Maxn 1100 char sa[Maxn]; int dp[Maxn][Maxn]; //dp[i][j]表示有i個字元,當前數字為j時,所有的總數 //注意有i個字元說明前面一共有1~i+1個不同的數字,dp[i-1]共有1~i個數字, //建立遞推時,如果當前為j,則前面小於j的不變,大於等於j的全部加一,這樣就從1~i變成了1~i+1 int la; int Mi[Maxn][2]; //Mi[i]表示上一個dp[i-1]下標小於等於j的值的總和 int main() { while(~scanf("%s",sa+1)) { int len=strlen(sa+1); for(int i=0;i<=len+10;i++) //初始化 { Mi[i][0]=Mi[i][1]=0; for(int j=0;j<=len+10;j++) dp[i][j]=0; } dp[0][1]=1; //沒有字元時,有一個數 且這個數為1 la=1; Mi[1][0]=1; //下標小於等於1的有一個 int pp=0; for(int i=1;i<=len;i++) { pp=pp^1; //當前狀態 int n=i+1;//當前為可能的取值,注意前面的之和相對大小有關 ll cur=0; for(int j=1;j<=n;j++) //列舉當前位的數值 { if(sa[i]=='I') //如果為增的話,前面的肯定是小於j的 dp[i][j]=(dp[i][j]+Mi[j-1][pp^1])%M; else if(sa[i]=='D') //減的話,前面是大於等於j的,加1後就變成了大於j的了 dp[i][j]=(dp[i][j]+(la-Mi[j-1][pp^1])%M+M)%M; else //如果無所謂的話,前面所有1-n-1個狀態都行 dp[i][j]=(dp[i][j]+la)%M; //用一個la記錄 Mi[j][pp]=(Mi[j-1][pp]+dp[i][j])%M;//求出當前的Mi cur=(cur+dp[i][j])%M; //求出當前的la } la=cur; //這題卡常數,多了幾個迴圈都不行 } ll ans=0; for(int i=1;i<=len+1;i++) //列舉最後的能夠佔有的值 ans=(ans+dp[len][i])%M; printf("%d\n",ans); } return 0; }