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...