http://acm.hdu.edu.cn/showproblem.php?pid=2955

(1)概率的预处理(常识):rp[i]=1-rp[i],并将概率相乘。若将概率相加(定式思维),案例是可以全过的,就麻烦了。。

(2)初始化dp数组:偷走0百万是安全的,这很关键(dp[0]=1),其他的都是危险的(dp[i]=0),因为背包必须装满;

(3)用sum 记录最大可能出现的值,结果也是从sum开始验证,符合安全条件的输出。

具体代码:

View Code
#include<stdio.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
int n, m[120];
float p, rp[120];
float dp[10100];
int main()
{
    int i, j, t, sum;
    while(scanf("%d", &t)!=EOF)
    {
        while(t--)
        {
            scanf("%f%d", &p, &n), p=1-p;
            sum=0;
            for(i=1;i<=n;i++)
                scanf("%d%f", &m[i], &rp[i]), sum+=m[i], rp[i]=1-rp[i];
            for(i=0;i<=sum;i++) dp[i]=0;
            dp[0]=1;
            for(i=1;i<=n;i++)
                for(j=sum;j>=m[i];j--)
                    dp[j]=max(dp[j], dp[j-m[i]]*rp[i]);
            for(i=sum;i>=0;i--)
                if(dp[i]>p) break;
            printf("%d\n", i);
        }
    }
    return 0;
}