HDU2955 01背包变体 xingxing在努力

  这道题的题意是小偷要去偷N家银行, 每家银行都有一个钱款数额Mi和被抓概率pi, 求小偷被抓的概率小于P的情况下所能偷到的钱数额的最大值(每家银行最多偷一次),由于每家银行最多偷一次, 所以这个题可以用01背包的思想来求解, 又因为小偷被抓会有很多种情况,并不好算,因此我们用他的反面小偷成功逃脱来算?这样题目就成了小偷在成功逃脱的概率大于1-P的情况下所能偷到的钱数最大值。。记f[i][j]为小偷在前i家银行恰好偷了j块钱成功逃脱的 概率最大值, 那么f[i][j] = max(f[i-1][j], f[i-1][j-W[i]]*(1-Pi[i])),该过程可以使滚动数组优化:代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
const double inf = 100000000000000;
const double eps = 1e-12;
int Mi[100 + 10];
double Pi[100 + 10];
double f[10000 + 100];
double P;
int N;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lf%d", &P, &N);
        P = 1 - P;
        int sum = 0;
        for(int i=1; i<=N; i++)
        {
            scanf("%d%lf", &Mi[i], &Pi[i]);
            sum += Mi[i];
        }
        for(int i=1; i<=sum; i++) f[i] = -inf;
        f[0] = 1;    //刚开始抢了0家银行, 逃脱概率为1
        int res = 0;
        for(int i=1; i<=N; i++)
        {
            for(int j=sum; j>=Mi[i]; j--)
            {
                f[j] = max(f[j], f[j-Mi[i]]*(1-Pi[i]));
                if(f[j]-P >= 0)
                    res = max(res, j);
            }
        }
        printf("%d\n", res);
    }
    return 0;
}
时间: 2025-01-20 04:31:23

HDU2955 01背包变体 xingxing在努力的相关文章

HDU2955(01背包)

Robberies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 18064    Accepted Submission(s): 6671 Problem Description The aspiring Roy the Robber has seen a lot of American movies, and knows that

HDU2546饭卡(变形01背包)

饭卡 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 11354    Accepted Submission(s): 3904 Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无

POJ2184 01背包变形 xingxing在努力

这道题乍一看就有了思路,大体就是定了其中一个值然后再求另外一个值的最大值, 然而代码实现好坑, 题意是奶牛有两个属性 Ai和Bi, 让你求Ai和Bi和的最大值,注意Ai的和不能为负整数, Bi也一样..假设我们定了Ai我们来看下状态方程:f[i][j] = max(f[i-1][j], f[i-1][j-A[i]]+B[i]).当A[i]为正的时候就是我们经常遇到的01背包,使用滚动数组倒着排一遍, 然而当A[i]为负的时候我们就应该从小推到大,这样才对..代码如下: #include <cst

HDU2639 第k小01背包 xingxing在努力

这个题目是求解第k小01背包, 我们只需要再多加一维表示容量为j时的价值即可..代码里面用了归并排序的思想来求解f[j][k], 代码如下: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int f[1000+10][35]; int A[35], B[35]; //A选 B不选 int W[100+10], V[100+10]; int N, v, K; v

POJ2923 状态压缩01背包 xingxing在努力

这道题算是很经典的状态压缩01背包了, 题意是有一个人要用两辆小汽车搬家, 每辆小汽车都有一个最大载重量, 现在有一些要搬的家具, 告诉你这些家具的重量, 问最少几次能将这些家具搬完(每次两辆汽车必须出动, 即使有一辆车什么都没有装)? 物品个数不超过10,根据经验一般有10存在的话都要带点暴力的色彩, 那么这道题就是先要预处理所有一次搬走的家具的集合, 然后就将其转化成了01背包的问假设d[i][j]是前i个家具中搬走了j(集合)家具所需要的最少次数那么d[i][j] = min(d[i-1]

HDU2602 01背包 xingxing在努力

很经典的01背包, 假设f(i, j)是将i个物品放入容量为j的背包, 那么可得到如下递推式f(i, j) = max(f(i-1, j) , f(i-1, j-c[i])+v[i]))....实现的话有两种方式, 一种是直接用二维数组实现, 另外一种是滚动数组, 不过要注意的是, 如果题意是让这些物品恰好装满背包,那么f(0, 0)为0其他为无穷大, 如果没必要恰好装满那就全部初始化为0: 代码如下: #include <cstdio> #include <cstring> #i

01背包水题篇之 HDU2955——Robberies

原来是想dp[i],表示不被抓概率为i所能抢到的最大钱(概率1-100) 后来看了别人的博客是dp[i]表示抢了i钱最大的不被抓概率,嗯~,弱菜水题都刷不动. 那么状态转移方程就是 dp[i]=max(dp[i],dp[i-money]*p),初始化dp(0~maxn)为0,dp[0]=1(1毛钱都没抢你抓个毛线啊,哥是良民~) 又是贴代码环节~ <span style="font-size:18px;">#include<iostream> #include&

【hdu2955】 Robberies 01背包

hdu2955 http://acm.hdu.edu.cn/showproblem.php?pid=2955 题意:盗贼抢银行,给出n个银行,每个银行有一定的资金和抢劫后被抓的概率,在给定一个概率P,表示盗贼愿意冒险抢劫所能承受的最大被抓概率. 思路:首先用1减去被抓概率,得到安全概率.那抢劫了多家银行后的安全概率就是这些银行各自的安全概率连乘起来.其实是01背包的变种, dp[j] 表示获得金额 j 时的安全概率.这里用滚动数组,得方程  dp[j] = max(dp[j], dp[i-a[i

hdu2955 Robberies (01背包)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955 Problem Description The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usually gets caught in the end, often because t