01背包(C题)

Description(C题)

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 they become too greedy. He has decided to work in the lucrative business of bank robbery only for a short while, before retiring to a comfortable job at a university.

For a few months now, Roy has been assessing the security of various banks and the amount of cash they hold. He wants to make a calculated risk, and grab as much money as possible.

His mother, Ola, has decided upon a tolerable probability of getting caught. She feels that he is safe enough if the banks he robs together give a probability less than this.

Input

The first line of input gives T, the number of cases. For each scenario, the first line of input gives a floating point number P, the probability Roy needs to be below, and an integer N, the number of banks he has plans for. Then follow N lines, where line j gives an integer Mj and a floating point number Pj .

Output

For each test case, output a line with the maximum number of millions he can expect to get while the probability of getting caught is less than the limit set.

Notes and Constraints
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0
A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent as the police have very low funds.

Sample Input

3
0.04 3
1 0.02
2 0.03
3 0.05
0.06 3
2 0.03
2 0.03
3 0.05
0.10 3
1 0.03
2 0.02
3 0.05

Sample Output

2
4
6

题意:

Roy想要抢银行,给出每个银行拥有的金钱和被抓的概率,给出Roy最大能承受的被抓概率P,求Roy不被抓的前提下最多偷盗的钱财。

可以承受的最大被抓的概率为p,即:如果逃跑的概率大于1-p则符合要求

01背包问题,把每个银行的储钱量之和当成背包容量,然后概率当成价值。这里是被抓的概率,我们把他转化成不被抓的概率,然后这里的和就可以转化成乘积。
最后不被抓的概率大于P(安全概率)(p=1-p)即可将对应的所能偷到的钱财相加,计算出最大值。

代码详解

#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=10005;
double dp[N];//需要转化一下思维,正常思维会是概率做下标
struct g {
    int v;
    double c;
} a[N];
int main()
{
    int n,t;
    double p;
    cin >> t;
    while(t--)
    {
        int sum=0;
        cin >>p>> n;
        for(int i=0; i<n; i++)
        {
            cin >>a[i].v>>a[i].c;
            sum+=a[i].v;//将价值求和
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int i=0; i<n; i++)
            for(int j=sum; j>=a[i].v; j--)//价值对应的概率储存
            {
                dp[j]=max(dp[j],dp[j-a[i].v]*(1-a[i].c));
            }
        for(int i=sum; i>=0; i--)
            if(dp[i]>1-p)
            {
                cout<<i<<endl;//找到最大价值不被抓的概率下标
                break;
            }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 01背包是一个经典的动态规划问,用于求解在限制物品体积或重量的情况下,能够获得的最大价值。 算法流程: 1. 定义状态:f[i][j] 表示前i个物品,体积不超过j的最大价值。 2. 状态转移:f[i][j] = max(f[i-1][j], f[i-1][j-v[i]]+w[i]),其中v[i]表示物品i的体积,w[i]表示物品i的价值。 3. 边界:f[0][j] = 0,0 <= j <= V,V为背包体积。 代码实现: ``` def knapsack(v, w, V): n = len(v) f = [[0 for j in range(V+1)] for i in range(n+1)] for i in range(1, n+1): for j in range(1, V+1): if j < v[i-1]: f[i][j] = f[i-1][j] else: f[i][j] = max(f[i-1][j], f[i-1][j-v[i-1]]+w[i-1]) return f[n][V] ``` 总结:01背包是一个典型的动态规划问,通过定义状态,计算状态转移方程,以及初始化边界,即可解决该问。 ### 回答2: 01背包是一个经典的动态规划问,也是算法和编程中常见的考察点之一。给定一组物品,每个物品都有自己的重量和价值,在限定的背包容量下,选择一些物品放入背包中,使得背包中物品的总价值最大化。 解决01背包的常用方法是使用动态规划。我们可以定义一个二维数组dp,其中dp[i][j]表示在前i个物品中,背包容量为j的情况下,能够达到的最大价值。 基本思路是,对于每个物品i,我们可以有两种选择:放入背包或者不放入背包。如果我们选择将物品i放入背包中,那么背包的容量将减少weight[i],同时总价值将增加value[i];如果我们选择不放入物品i,那么背包的容量和总价值都不会发生变化。因此,我们可以通过比较这两种选择的结果,取较大的那个来更新dp[i][j]。 具体的动态规划转移方程如下: 1. 如果物品i的重量大于背包容量j,即weight[i] > j,那么dp[i][j] = dp[i-1][j],即不放入物品i,结果和前i-1个物品相同。 2. 如果物品i的重量小于等于背包容量j,即weight[i] <= j,有两种选择: a. 放入物品i:dp[i][j] = dp[i-1][j-weight[i]] + value[i] b. 不放入物品i:dp[i][j] = dp[i-1][j],结果和前i-1个物品相同。 3. 最终的结果为dp[n][c],即在前n个物品中,背包容量为c的情况下,所能达到的最大价值,其中n为物品的总个数,c为背包的容量。 通过动态规划的思想,我们可以逐步计算出dp数组的所有值,并找出最终的结果。该方法的时间复杂度为O(n*c),空间复杂度为O(n*c)。 在实际应用中,我们可以根据目的具体要求进行相应的优化,如利用一维数组进行降维优化、使用滚动数组减少空间复杂度等。不同的优化方法可以根据具体情况灵活运用,以提高算法的效率。 ### 回答3: 01背包是一种经典的动态规划问,它是指在一组不同重量和不同价值的物品中,选择一部分物品装入背包,使得背包中物品的总价值最大,同时不能超过背包的重量限制。 解决01背包的关键是构建一个二维数组dp,其中dp[i][j]表示在前i个物品中,背包容量为j时的最大价值。根据动态转移方程dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]),可以逐步更新dp数组,最终得到dp[n][W]的最大价值。 具体的实现中,我们可以使用两层循环来更新dp数组。外层循环遍历物品,内层循环遍历背包容量,通过比较选择是否将当前物品放入背包。当物品的重量小于等于背包容量时,我们可以选择放入背包,此时背包中的总价值为dp[i-1][j-w[i]]+v[i];如果不放入背包,背包中的总价值为dp[i-1][j],取两者的较大值更新dp[i][j]。如果物品的重量大于背包容量,则不可能放入背包,即dp[i][j]保持不变。 最后,dp[n][W]即为所求的最大价值。可以通过反向遍历dp数组,根据dp[i][j]和dp[i-1][j]是否相等,判断物品i是否放入了背包,从而确定所选择的物品。 总之,通过动态规划的思想,我们可以解决01背包。这个问有着广泛的应用,在资源分配、装箱、旅行路线规划等领域都有着重要的作用。 希望以上回答对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值