兩道題都是動態規劃233。。。c++
1:算法
想法:優化
咱們看1 1 0, 咱們先計算1 2 3知足1 1個數, 如今有來了一個4要求知足1 1 0;spa
咱們依次將1,2,3,4放在最後一位, 那麼前三個數也能夠看做一個排列;code
1 2 4 :3; (實際排列1 2 4和排列 1 2 3沒有區別) 那麼當3在最後一位時,咱們只要獲得blog
前三位以3(至關於此時的4)結尾的合法數目便可。這樣就獲得了子問題的結構遞歸
狀態定義dp[i][j] : (i+1)數字的排列知足前i個要求並以j結尾的合法數目ci
狀態轉移: a[i]==1, 則x[i]>x[i+1]。dp[i][j]=sum dp[i-1][k] (j<=k<=i)it
a[i]==0, 則x[i]<x[i+1]。dp[i][j]=sum dp[i-1][k] (1<=k<=j-1)class
爲了進一步優化算法, 定義前綴和sum[i][j]=sum dp[i][k] (1<=k<=j)
時間複雜度O(n), 解決
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int N=1e3+7; 5 const int mod=1e9+7; 6 LL dp[N][N]; 7 LL sum[N][N]; 8 int a[N]; 9 int n; 10 int main() 11 { 12 cin>>n; 13 for (int i=1;i<n;i++) cin>>a[i]; 14 if (a[1]) { dp[1][1]=1; sum[1][2]=sum[1][1]=1; } 15 else { dp[1][2]=1; sum[1][2]=1; } 16 for (int i=2;i<n;i++) 17 for (int j=1;j<=i+1;j++) { 18 if (a[i]) dp[i][j]=(sum[i-1][i]-sum[i-1][j-1]+mod)%mod; 19 else dp[i][j]=sum[i-1][j-1]; 20 sum[i][j]=(sum[i][j-1]+dp[i][j])%mod; 21 } 22 printf("%lld\n", sum[n-1][n]); 23 return 0; 24 }
2:
想法: 其實這道題我以爲很easy, 由於數據量並不大。
對於n個紅球,m個籃球,A贏的狀況有這樣3種:
(1)A 先手抽中紅球的機率
(2)在A,B都抽中籃球的狀況下
2.1 C抽中紅球以後A贏的機率
2.2 C抽中籃球以後A贏的機率
每一輪抽中以後,球的數量會減小,這就是一個動態規劃問題
狀態定義:dp[n][m], n紅m藍 A贏的機率(不會遞推, 只會遞歸。。。233)