P3985 不开心的金明 - 洛谷 (01背包变形)

简介: 笔记

P3985 不开心的金明 - 洛谷


题意

金明今天很不开心,家里购置的二手房就要领钥匙了,房里并没有一间他自己专用的很宽敞的房间。更让他不高兴的是,妈妈昨天对他说:“你需要购买哪些物品,怎么布置,你说了不算(有很大的限制),而且不超过 W 元钱。”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的 W 元。于是,他把每件物品规定了一个重要度整数 p i 表示。他还从因特网上查到了每件物品的价格 v i (都是整数元)。


妈妈看到购物单后进行了审查,要求购物单上所有的物品价格的极差(最贵的减去最便宜的)不超过 3(当然金明至今不知道为什么会这样)。他希望在不超过 W 元(可以等于 W 元)的前提下,使购买的重要度总和 ∑ p i

 的最大。


请你帮助金明设计一个满足要求的购物单,你只需要告诉我们重要度的最大的和。


数据范围

110.png


思路

从数据范围可以看出如果使用背包的话,会超空间范围。


这时注意题目中的要求 所有物品的极差不超过3 ,这说明当 n 个物品中的最小值超过300时,无需考虑体积的限制,贪心地找重要度最大的物品即可。这是因为,假设我们买了100件物品(最多件),那么都买价值最大的和都买价值最小的物品所花费的总钱数的差值不超过300,但此时所有物品中价值最小的物品的价格超过300,所以无法再买一件产品,这时,只需要贪心地考虑重要度即可。


如果最小值小于300 那么进行01背包即可


代码

#include<bits/stdc++.h>
// #define int long long
#define INF 0x3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define rep(i, st, ed) for (int (i) = (st); (i) <= (ed);++(i))
#define pre(i, ed, st) for (int (i) = (ed); (i) >= (st);--(i))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
template<typename T> inline T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<typename T> inline T lowbit(T x) { return x & -x; }
template<typename T> T qmi(T a, T b = mod - 2, T p = mod) { T res = 1; b %= (p - 1 == 0 ? p : p - 1); while (b) { if (b & 1) { res = (LL)res * a % p; }b >>= 1; a = (LL)a * a % p; }return res % mod; }
const int N = 300 * 101;
int n, w;
int dp[N];
struct Node {
  int v, p;
  bool operator<(const Node& w)const {
    return this->p > w.p;
  }
}node[200];
void solve() {
  cin >> n >> w;
  int minn = INF;
  for (int i = 1; i <= n; ++i) {
    cin >> node[i].v >> node[i].p;
    minn = min(minn, node[i].v);
  }
  if (minn >= 300) {
    sort(node + 1, node + 1 + n);
    int sum = 0, res = 0;
    for (int i = 1; i <= n; ++i) {
      if (sum + node[i].v > w)break;
      else {
        sum += node[i].v;
        res += node[i].p;
      }
    }
    cout << res << endl;
  }
  else {
    int res = 0;
    for (int i = 1; i <= n; ++i) {
      for (int j = w; j >= node[i].v; --j) {
        dp[j] = max(dp[j], dp[j - node[i].v] + node[i].p);
      }
    }
    for (int i = 0; i <= w; ++i) {
      res = max(res, dp[i]);
    }
    cout << res << endl;
  }
}
signed main() {
  // int T; cin >> T;
  // while (T--)
  solve();
  return 0;
}


目录
相关文章
【动态规划刷题 6】 删除并获得点数&& 粉刷房子
【动态规划刷题 6】 删除并获得点数&& 粉刷房子
|
6月前
|
算法
【动态规划专栏】背包问题:1049. 最后一块石头的重量 II
【动态规划专栏】背包问题:1049. 最后一块石头的重量 II
56 0
|
6月前
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
41 0
|
算法 Java
代码随想录算法训练营第三十四天 | LeetCode 860. 柠檬水找零、406. 根据身高重建队列、452. 用最少数量的箭引爆气球
代码随想录算法训练营第三十四天 | LeetCode 860. 柠檬水找零、406. 根据身高重建队列、452. 用最少数量的箭引爆气球
64 0
|
机器学习/深度学习
剑指offer 13. 剪绳子
剑指offer 13. 剪绳子
73 0
可能你已经刷了很多01背包的题,但是真的对01背包领悟透彻了吗?,看我这一篇,使君对01背包的理解更进一步【代码+图解+文字描述】
可能你已经刷了很多01背包的题,但是真的对01背包领悟透彻了吗?,看我这一篇,使君对01背包的理解更进一步【代码+图解+文字描述】
【寒假每日一题】AcWing 4652. 纸张尺寸
目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解
82 0
代码随想录刷题|LeetCode 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
代码随想录刷题|LeetCode 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
代码随想录刷题|LeetCode 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
|
C++
蓝桥杯练习题三 - 纸牌三角形(c++)
蓝桥杯练习题三 - 纸牌三角形(c++)
123 0