P3985 不开心的金明
作者:互联网
P3985 不开心的金明
题目描述
金明今天很不开心,家里购置的二手房就要领钥匙了,房里并没有一间他自己专用的很宽敞的房间。更让他不高兴的是,妈妈昨天对他说:“你需要购买哪些物品,怎么布置,你说了不算(有很大的限制),而且不超过W元钱。”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的W元。于是,他把每件物品规定了一个重要度整数pi表示。他还从因特网上查到了每件物品的价格vi(都是整数元)。
妈妈看到购物单后进行了审查,要求购物单上所有的物品价格的极差(最贵的减去最便宜的)不超过3(当然金明至今不知道为什么会这样)。他希望在不超过W元(可以等于W元)的前提下,使购买的重要度总和∑pi的最大。
请你帮助金明设计一个满足要求的购物单,你只需要告诉我们重要度的最大的和。
输入格式
输入的第1行,为两个正整数,用一个空格隔开:
n W (其中W表示总钱数,n为希望购买物品的个数。)
从第2行到第n+1行,第j行给出了编号为j-1的物品的基本数据,每行有2个非负整数v p (其中v表示该物品的价格,p表示该物品的重要度)
输出格式
输出只有一个正整数,为不超过总钱数的物品的重要度的总和的最大值
输入样例
5 10
2 800
5 400
5 300
3 400
2 200
输出样例
1600
数据范围
1 ≤ N ≤ 100
1 ≤ W ≤ 1e9
1 ≤ vi ≤ 1e9
对所有的i=1,2,3,…,N,min(vi) ≤ vi ≤min(vi) + 3
1 ≤ pi ≤ 1e7
解题思路
这里有几个比较重要的条件需要先明确一下对所有的i=1,2,3,…,N,min(vi) ≤ vi ≤min(vi) + 3
这个条件说明了只有四种状态的价格存在,即为0 1 2 3
。极差是3,最多购买件数为100,所以这里买全都买最便宜的和全都买最贵的物品的价格相差就是 3 * 100 = 300。
300是蛮重要的一个点,我们想如果最便宜的物品的价格超过300,假设最便宜的是301,则最贵的价格就为304,那么我们全都买最贵的和全都买最便宜的价格分别是 30100和30400, 价格相差了300,这300即买不了最便宜的物品更买不了最贵的物品,所以最便宜的物品价格一旦超过了300,此时我们就可以用贪心来做,而最小值没有超过300时我们就可以用01背包来做。
还有一个点就是题目中说到n件物品的价格之和 >= w,那么超过300后的购买件数就为w/minn_val或者 w/maxx_val都可以。
参考代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 7;
const int inf = 2147483647;
const double PI = acos(-1.0);
int val[maxn], pi[maxn];
ll dp[maxn] = {0};
int main()
{
int n, w, maxx_val = 0, minn_val = inf;
scanf("%d %d", &n, &w);
for (int i = 1; i <= n; i++)
{
scanf("%d %d", &val[i], &pi[i]);
maxx_val = max(maxx_val, val[i]);
minn_val = min(minn_val, val[i]);
}
if (minn_val <= 300)
{
for (int i = 1; i <= n; i++)
for (int j = w; j >= val[i]; j--)
dp[j] = max(dp[j], dp[j - val[i]] + pi[i]);
printf("%lld\n", dp[w]);
}
else
{
ll sum = 0;
sort(pi + 1, pi + n + 1);
for (int i = 1; i <= w / maxx_val; i++)
sum += pi[n - i + 1];
printf("%lld", sum);
}
return 0;
}
标签:开心,val,P3985,vi,300,int,物品,pi,金明 来源: https://blog.csdn.net/SZTU_ZJB/article/details/123228518