簡單說下背景,有個人要搶銀行,對於每個銀行有銀行裏存的錢數,以及搶了以後被抓住的概率,對於每組數據有一個可以被接受的最大被抓概率(我們稱px),和要強的銀行個數。首先開始我自己沒有讀懂題只是湊了一下數據發現可以是一個以概率爲揹包容量的01揹包,然後將概率轉化爲了整數再用普通01揹包裝銀行的錢數,然而無論乘多少倍將概率化整是無法真正實現的。所以正確的思路是以總共搶的錢數作爲狀態,對於每一個錢數存在一個最大逃脫概率(注意這裏是逃脫概率即1-被抓概率)所以這裏可以得到狀態轉移方程
dp[j]=max(dp[j],dp[j-v[i]]*(1-p[i]));
對於最後求完的dp數組從中找到大於px所能搶到的最多錢數。得解
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
{
int t,n;
int v[200];
double dp[200000],p[200],vx;
scanf("%d",&t);
while(t--)
{
int m=0;
memset(dp,0,sizeof(dp));
dp[0]=1;
scanf("%lf%d",&vx,&n);
for (int i=0;i<n;i++)
{
scanf("%d%lf",&v[i],&p[i]);
m += v[i];
}
for (int i=0;i<n;i++)
{
for(int j=m;j>=v[i];j--)
{
dp[j]=max(dp[j],dp[j-v[i]]*(1-p[i]));
}
}
for(int i=m;i>=0;i--)
{
if(dp[i]>=1-vx)
{
printf("%d\n",i);
break;
}
}
}
return 0;
}