题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955
这个题目简单也不简单,谁都能看出来是0-1背包问题,但是怎么背包法还是要想想的
开始想直接方法概率,用普通背包做,但是小了wa大了TLE
最后想到反着来,因为银行里面的钱是整数,而且钱有限,所以呢
可以把钱作为代价来dp
dp[i]表示抢i钱最大生还的希望,dp[0]=1其他的初始化为0
最后找一个生还概率大于1-p的最大的下标值输出
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define maxn 15000
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
#define inf -1e12
int n,num;
double p;
double dp[maxn],c[maxn];
int m[maxn];
int main(){
int i,j,k,t,ans;
scanf("%d",&t);
double total;
while(t--){
scanf("%lf%d",&p,&n);
p=1-p;
num=0;
total=0;
for(i=0;i<n;i++){
scanf("%d%lf",&m[i],&c[i]);
num+=m[i];
c[i]=1-c[i];
}
total=n-p;
memset(dp,0,sizeof(dp));
dp[0]=1;
for(i=0;i<n;i++)
for(j=num;j>=m[i];j--)
dp[j]=MAX(dp[j],dp[j-m[i]]*c[i]);
ans=0;
for(i=0;i<=num;i++)
if(dp[i]>=p) ans=i;
printf("%d\n",ans);
}
return 0;
}