題目點我
題目大意:給了
思路:01揹包問題,一開始想把概率取對數做揹包容量,發現行不通。要用收益當揹包容量,用安全概率當作揹包價值。狀態轉移方程如下:
其中
這道題的揹包要恰好裝滿,所以開始要把
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define INF -1
#define MAX 10010
#define NUM 105
double dp[MAX];
double max(double a, double b){
return a > b ? a : b;
}
void ZeroOnePack(double *f, int cost, double p, int vol){
for(int i = vol; i >= cost; i--)
f[i] = max(f[i], f[i - cost] * (1 - p));
}
int main(){
int T, N, i, M[NUM], MaxM = 0;
double P[NUM], Psafe;
scanf("%d", &T);
while(T--){
scanf("%lf %d", &Psafe, &N);
for(i = 0; i < N; i++){
scanf("%d %lf", &M[i], &P[i]);
MaxM = MaxM > M[i] ? MaxM : M[i];
}
for(i = 1; i < N * MaxM; i++)
dp[i] = INF;
dp[0] = 1; //沒搶錢的安全概率 = 1
for(i = 0; i < N; i++)
ZeroOnePack(dp, M[i], P[i], N * MaxM);
for(i = N * MaxM; i >= 0; i--){
if(dp[i] >= (1 - Psafe)){
printf("%d\n", i);
break;
}
}
memset(dp, 0, sizeof(double)*MAX);
}
return 0;
}