1. 程式人生 > 實用技巧 >codeforces---167BWizards and Huge Prize 概率DP

codeforces---167BWizards and Huge Prize 概率DP

題目連結:https://codeforces.com/problemset/problem/167/B

題目大意:有n場比賽,你至少要贏l次才算優秀,你有一個大小為k的包,每場比賽的勝率為$p_i$,每場比賽贏得的獎品為$a_i$如果$a_i<0$則是獎品,否則就是一個容量為$a[i]$的揹包。問你在優秀的時候拿走所以贏得獎品的概率。

Examples

Input
3 1 0
10 20 30
-1 -1 2
Output
0.300000000000
Input
1 1 1
100
123
Output
1.000000000000

DP。。。真的有點無力。。。。

設定狀態為$dp[i][j][k]$,表示為前$i$場比賽贏得$j$場後的揹包剩餘空間$k$。由於比賽的順序是無序的,那麼我們可以對初始狀態揹包容量+200(因為最多200個獎品),那麼這樣就可以隨便拿了,最後確定狀態的時候小於200的就直接捨棄了。

以下是AC程式碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int mac=210;

int a[mac];
double p[mac];
double dp[mac][mac][2*mac];

int main()
{
    int n,l,v;
    scanf ("%d%d%d",&n,&l,&v);
    for (int i=1; i<=n; i++)
        scanf (
"%lf",&p[i]),p[i]/=100; for (int i=1; i<=n; i++) scanf ("%d",&a[i]); dp[0][0][v+200]=1; for (int i=0; i<n; i++) for (int j=0; j<=i; j++) for (int k=0; k<=400; k++){//列舉空間 int last=min(k+a[i+1],400); dp[i+1][j][k]+=dp[i][j][k]*(1
-p[i+1]);//本場失敗 if (last>0) dp[i+1][j+1][last]+=dp[i][j][k]*p[i+1]; } double ans=0; for (int i=200; i<=400; i++) for (int j=l; j<=n; j++) ans+=dp[n][j][i]; printf("%.10f\n",ans); return 0; }