牛客練習賽35 B(簡單dp,ORZ)
阿新 • • 發佈:2019-01-05
思路:想明白了發現真的簡單dp。。。我還是太菜了
程式碼如下:
/* 果不其然。簡單dp...是我菜,不是題目難 做這題首先我沒想到dp(哭暈) 看了題解半天。一臉懵逼 既然dp解那麼先考慮最優解的結構特徵 先想只用一維表示,dp[i]:在i這個位置上得到的最多的方案數 上面是不行的,因為dp[i]沒有記錄i位置上是什麼元素,導致下一步無法轉移(條件中說了,不能有超過連續A個母音,只用dp[i]中的資訊無法知道,下一位能取什麼); 既然一維不行,在動態規劃的思考過程中,解決的方案應該是提高維數,從在狀態中獲得更多的資訊 觀察一維失敗的原因,是不知道上一位放的是什麼,所以給每個狀態多兩個位置存是取什麼值 dp[i][0,1]:0代表這個位上是母音;1是子音 (大佬們用這麼多就夠了。。。但是我想不通,所以小弟再加一維) dp[i][0,1][j]:j代表算上i位有連續多少個相同元素 這樣子問題就能描述清楚了 */ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<queue> #include<cmath> using namespace std; #define maxn 5009 #define inf 40000000 typedef pair<int,int >P; const long long mo=1e9+7; long long dp[maxn][2][100]; int n,a,b; int main() { int T; //printf("%lld\n",mo*1000); cin>>T; while(T--) { memset(dp,0,sizeof(dp)); scanf("%d%d%d",&n,&a,&b); dp[1][0][1]=5; dp[1][1][1]=21; long long ans=26; for(int i=2;i<=n;i++) { //i位=0,有1個0;(即前面全是1) for(int k=1;k<=min(b,i-1);k++) { dp[i][0][1]+=dp[i-1][1][k]; } dp[i][0][1]=(dp[i][0][1]*5%mo); ans+=dp[i][0][1]; //i位=0,有k(k>=2)個0; for(int k=2;k<=min(a,i);k++) { dp[i][0][k]=(dp[i-1][0][k-1]*5%mo); ans+=dp[i][0][k]; } //i位=1,有1個1;(即前面全是0) for(int k=1;k<=min(a,i-1);k++) { dp[i][1][1]+=dp[i-1][0][k]; } dp[i][1][1]=(dp[i][1][1]*21%mo); ans+=dp[i][1][1]; //i位=1,有k(k>=2)個1; for(int k=2;k<=min(b,i);k++) { dp[i][1][k]=(dp[i-1][1][k-1]*21%mo); ans+=dp[i][1][k]; } ans%=mo; } printf("%lld\n",ans); } return 0; }