遞推DP 加深

2021-09-02 07:25:40 字數 1271 閱讀 2608

zoj 3747

題意:給n個士兵排隊,每個士兵三種g、r、p可選,求至少有m個連續g士兵,最多有k個連續r士兵的排列的種數。

都轉化為至多的士兵連續的個數。

令集合a=

集合b=

c=a-b=。

在轉化要如何求 至多x個g士兵連續,至多y個士兵連續

dp[i][0]至多i個g 的方案數

dp[i][1]至多i個r 的方案數

dp[i][2]第i個為p 的方案數

對g士兵遞推:

當i<=x時

dp[i][0]=dp[i-1][0]+dp[i-1][1]+dp[i-1][2];

當i=x+1時候

dp[i][0]=dp[i-1][0]+dp[i-1][1]+dp[i-1][2]-1; 減去的是x+1位置為g士兵的時候

當i>x+1的時候

dp[i][0]=dp[i-1][0]+dp[i-1][1]+dp[i-1][2]-dp[i-x-1][1]-dp[i-x-1][2]; 此時要減去i前面已經出現連續u個g的情況,即從i-u到i-1這一段都是g,

那麼i-1-u的位置可以是p或者r,

對士兵r遞推:

同理

#include #include #define x 10005

#define inf 0x3f3f3f3f

#define pi 3.141592653589793238462643383

#define io ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);

#pragma comment(linker, "/stack:1024000000,1024000000")

using namespace std;

typedef long long ll;

const ll mod=1e9+7;

const int maxn=1e6+10;

ll dp[maxn][4];

int n,m,k;

ll solve(int x,int y)//dp[i][0]至多i個g dp[i][1]至多i個r dp[i][2]第i個為p

return (dp[n][0]+dp[n][1]+dp[n][2])%mod;

}int main()

return dp[n][0]+dp[n][1];

}int main()

cout<}

return 0;

}

!hdu 1203 dp (加深理解)

題意 小明有n元錢,他想申請國外的學校,申請第i所學校要用si的費用,申請成功的概率是pi,求小明至少能申請成功一所學校的概率。分析 概率當然是從反面求最小值。狀態轉移方程 dp i min dp j p i dp i 我想錯了,我就按照以前的dp的套路依照陣列來遍歷,還先排了序,dp i 代表申請...

每日演算法 計數DP和遞推DP

計數pd就是emm感覺求那種什麼路徑和的就是計數那一類的,再概括一下就是可以不用其他操作直接將它相鄰或者說符合要求的 求和,就是下乙個位置的值。回到這題 用動規很好做。我們想要知道 0,0 到終點的位置的路徑,只需要知道終點已左終點已下的路徑為多少就行了。dp i j 0,0 到 i,j 位置的路徑...

折線分割平面 遞推dp

我們看到過很多直線分割平面的題目,今天的這個題目稍微有些變化,我們要求的是n條折線分割平面的最大數目。比如,一條折線可以將平面分成兩部分,兩條折線最多可以將平面分成7部分,具體如下所示。input 輸入資料的第一行是乙個整數c,表示測試例項的個數,然後是c 行資料,每行包含乙個整數n 0output...