2955 ACM 杭电 抢银行 01背包 乘法

时间:2023-03-08 21:48:04

2955 ACM 杭电 抢银行 01背包 乘法2955 ACM 杭电 抢银行 01背包 乘法


题意:
强盗抢银行,在不被抓住的情况下,想尽量多的偷点钱。已知各个银行的金钱和被抓的概率,以及强盗能容忍的最大不被抓的概率(小于等于该概率才能不被抓),求最多能抢到钱?

并不是简单的01背包问题?
1.概率是浮点数
2.最大不被抓的概率不是简单相加,由概率论可知,要抢的几家银行同时不被抓,要相乘。P=(1-P1)(1-P2)(1-P3) (P为最大不被抓的概率,P1 P2 P3为各个银行被抓的概率)

难点:
通常的01背包模板:
for(int j=v;j>=a[i].w;j–)//v是容积(拥有的总资金.)
{
dp[j]=max(dp[j],dp[j-a[i].w]+a[i].val);
}
如何和01背包联系起来。可以这么思考:钱作为v 然后dp数组里存逃跑的概率。

for(int j=total_val;j>=val[i];j--)//total_val是总钱数
{
dp[j]=max(dp[j],dp[j-val[i]]*(1-prob[i]));
}

状态转移方程:

dp[j]=max(dp[j],dp[j-val[i])(1-prob[i])); …….dp[i]表示当抢到i元钱 时,不被抓的最小概率值。*

最后输出前遍历dp,从钱数大到小遍历,一旦满足概率:dp[i] > (1 - P),输出值,跳出循环。

#include<stdio.h>
#include<string.h> #define max(a,b) (a>b)?a:b
#define NN 50005 int main()
{
int T,N,val[NN];
double P,dp[NN],prob[NN];
scanf("%d",&T);
while(T--)
{
scanf("%lf%d",&P,&N);
int total_val=0;
for(int i=0;i<N;i++)
{
scanf("%d%lf",&val[i],&prob[i]);
total_val+=val[i];
}
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=0;i<N;i++)
for(int j=total_val;j>=val[i];j--)
{
dp[j]=max(dp[j],dp[j-val[i]]*(1-prob[i]));
} for(int i = total_val; i >= 0; i --)
{
if(dp[i] > (1 - P))
{
printf("%d\n", i);
break;
}
}
}
}

](https://img-blog.****.net/2018080611055363?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjEwMDQ3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)