zoukankan      html  css  js  c++  java
  • codeforces 366C Dima and Salad 【限制性01背包】

    <题目链接>

    题目大意:

    在一个水果篮里有n种水果,并且这些水果每一种都有一个美味度和一个卡路里的属性, 小明要从这些水果中选出来一些做一个水果沙拉, 并且要求他的水果沙拉的美味度是卡路里的k倍,问小明是否可以做出这么一个水果沙拉,若不能输出-1,否则输出复合要求的最大的美味值。

    解题思路:

    题目的限制条件为物品的价值总和与卡路里的比值要为K,这个控制,于是我们将卡路里总和乘到的右边,然后移项,可得(a1-k*b1)+(a2-k*b2)+……+(an-k*bn)=0。因此就将 (ai-k*bi)作为物品i的一个新的属性,就将本问题转化为了01背包问题, 将(ai-k*bi)看成物品的重量,ai为物品的价值,0为背包的总容量。但是如果这样的话,(ai-k*bi)会出现负数。

    为了处理这个问题,有两种处理方案;

    一:将等式两边同时+N,使得 (ai-k*bi)全部为正

    二:用两个dp,正的跑一遍,负的跑一遍,然后在把它们相加就是答案,至于题目的限制条件,则可以通过取相同的 i 值来实现,因为dd[i]中的体积 i 为实际体积的相反数。

    下面的是第二种方案:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    const int maxn = 20000;
    #define INF 0x3f3f3f3f
    int dp[maxn], dd[maxn];
    struct node
    {
        int val, k;
        int cnt;
    };
    
    int main()
    {
        int n, m;
        while (scanf("%d %d", &n, &m) != EOF)
        {
            node arr[110];
            for (int i = 1; i <= n; i++)
                scanf("%d", &arr[i].val);
            for (int i = 1; i <= n; i++)
            {
                scanf("%d", &arr[i].k);
                arr[i].cnt = arr[i].val - m * arr[i].k;
            }
    
            memset(dp, -INF, sizeof(dp));         //初始化为负无穷是为了能够使dp[j]表示恰好装满 i 体积的情况
            memset(dd, -INF, sizeof(dd));
            dp[0] = dd[0] = 0;
            for (int i = 1; i <= n; i++)
            {
                if (arr[i].cnt >= 0)
                {
                    for (int j = 11000; j >= arr[i].cnt; j--)
                    {
                        dp[j] = max(dp[j], dp[j - arr[i].cnt] + arr[i].val);
                    }
                }
                else
                {
                    arr[i].cnt = -arr[i].cnt;
                    for (int j = 11000; j >= arr[i].cnt; j--)
                    {
                        dd[j] = max(dd[j], dd[j - arr[i].cnt] + arr[i].val);
                    }
                }
            }
    
            int ans = -0x3f;
            for (int i = 0; i <= 11000; i++)
            {
                if (dp[i] == 0 && dd[i] == 0)continue;         //因为ans初始化为-0x3f,所以要跳过dp[0]==dd[0]==0的情况
                ans = max(ans, dd[i] + dp[i]);                //因为dp[i],dd[i]表示恰好装满i容量的最大价值,所以,题目的限制条件:(ai-k*bi)的总和=0,就可以通过dd[i],dp[i]取相同的i值来实现
            }
            ans == -0x3f ? printf("-1
    ") : printf("%d
    ", ans);     
    
        }
        return 0;
    }

    2018-07-28

  • 相关阅读:
    在Electron中最快速预加载脚本
    Babel是什么?
    node、npm、chrome、v8、sandbox是什么?
    我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
    NN[神经网络]中embedding的dense和sparse是什么意思?
    记一次失败的docker排障经历
    paddlepaddle关于使用dropout小案例
    paddlepaddle如何预加载embedding向量
    最近在部署推荐系统环境时,遇到一个很奇葩都问题
    fluid.io.load_inference_model 载入多个模型的时候会报错 -- [paddlepaddle]
  • 原文地址:https://www.cnblogs.com/00isok/p/9380339.html
Copyright © 2011-2022 走看看