题目链接:杭电oj高校二级域名一律不得访问,有机会再补上(flag)
题意:题意读了很久才懂。一个强盗想要抢劫,他有一个被抓的最大概率,他抢劫每个银行都有一个相应的概率,希望可以尽可能多的抢劫,但是总的被抓概率不会低于给定的概率。
思路:可以看出来是一个01背包,但是如果直接用最大概率作为背包由于精度和时间复杂度都不可能满足。所以应该用所有的银行总价值作为背包,被抓概率作为价值。但是这里的概率不能简单相加,因为抢劫每个银行都是一个独立事件,所以想要都不被抓的话最后逃脱的概率应该是每次逃脱概率的积。因为dp[i]存储的是抢劫了当前价值时的最大逃脱概率,所以只要从最大下标开始遍历,遇到第一个满足逃脱概率的下标i输出即可。要注意的是因为这里是将银行的总价值填进dp里,所以要注意dp的下标范围。
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string>
#include <cstring>
#include <map>
#include <iostream>
#include <string.h>
using namespace std;
typedef long long ll;
const int maxn = 105;
double dp[10004];
double c[maxn];
int w[maxn];
double V;
int n;
int sum;
void OneZeroPack(int cost,double weight)
{
for(int v=sum;v>=cost;v--){
dp[v]=max(dp[v],dp[v-cost]*weight);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
memset(dp,0,sizeof(dp));
scanf("%lf%d",&V,&n);
sum=0;
for(int i=0;i<n;i++){
scanf("%d%lf",&w[i],&c[i]);
sum+=w[i];
}
dp[0]=1;
for(int i=0;i<n;i++){
OneZeroPack(w[i],1-c[i]);
}
for(int i=sum;i>=0;i--){
if(dp[i]>1-V) {printf("%d\n",i);break;}
}
}
return 0;
}