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;
}


目录
相关文章
|
7月前
LeetCode题:174. 地下城游戏
LeetCode题:174. 地下城游戏
65 0
LeetCode题:174. 地下城游戏
|
7月前
|
算法
算法刷题(二十二):宝石与石头
算法刷题(二十二):宝石与石头
70 0
【动态规划刷题 5】 最小路径和&&地下城游戏
【动态规划刷题 5】 最小路径和&&地下城游戏
【动态规划刷题 6】 删除并获得点数&& 粉刷房子
【动态规划刷题 6】 删除并获得点数&& 粉刷房子
|
6月前
|
人工智能 程序员 定位技术
老程序员分享:NOIP2016天天爱跑步(树上差分)
老程序员分享:NOIP2016天天爱跑步(树上差分)
31 0
|
7月前
【编程题-错题集】kotori和气球(组合数学)
【编程题-错题集】kotori和气球(组合数学)
|
7月前
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
42 0
|
算法
【学会动态规划】地下城游戏(10)
【学会动态规划】地下城游戏(10)
61 0

相关实验场景

更多