洛谷P2370 yyy2015c01 的 U 盘(贪心 + 二分 + dp)
题目
在 2020 年的某一天,我们的 yyy2015c01 买了个高端 U 盘。
题目描述
你找 yyy2015c01 借到了这个高端的 U 盘,拷贝一些重要资料,但是你发现这个 U 盘有一些问题:
这个 U 盘的传输接口很小,只能传输大小不超过 LL 的文件。
这个 U 盘容量很小,一共只能装不超过 SS 的文件。
但是你要备份的资料却有很多,你只能备份其中的一部分。
为了选择要备份哪些文件,你给所有文件设置了一个价值 Vi,你希望备份的文件总价值不小于p。
但是很快你发现这是不可能的,因为 yyy2015c01 的传输接口太小了,你只有花钱买一个更大的接口(更大的接口意味着可以传输更大的文件,但是购买它会花费更多的钱)。
注意:你的文件不能被分割(你只能把一个文件整个的传输进去,并储存在U盘中),
你放在 U 盘中文件的总大小不能超过 U 盘容量。
现在问题来了:你想知道,在满足 U 盘中文件价值之和不小于 p 时,最小需要多大的接口。
输入格式
第 11 行,三个正整数 n,p,S分别表示文件总数,希望最小价值 p ,硬盘大小。
接下来 n 行,每行两个正整数Wi,Vi,表示第 i 个文件的大小和价值。
输出格式
输出一个正整数表示最小需要的接口大小。
如果无解输出 No Solution!。
输入输出样例
输入
3 3 5
2 2
1 2
3 2
输出
2
输入
2 3 505
1 2
500 1
输出
500
输入
3 3 2
2 2
1 2
3 2
输出
No Solution!
输入
4 5 6
5 1
5 2
5 3
1 1
输出
No Solution!
说明/提示
1 <= n, Wi, S <= 10^3, 1 <= Vi <= 10^6, 1 <= p <= 10^9
数据较小,请勿乱搞。
样例解释 1:买一个大小为 2 接口,把物品 1 、2 放进U盘。
样例解释 2:买一个大小为 500 的接口。
样例解释 3:本来可以买大小为 2 的接口,可是 U 盘容量放不下足够的文件。
思路:贪心 + dp + 二分. 贪心:其实就是将文件大小按从小到大进行排序,毕竟它是要求最小的接口,所以肯定希望放的是近可能小的文件。此外,它需要满足文件价值至少要是p,那么可以用二分找出它们价值总和的边界值是否大于或等于p,假如找得到,最大的文件就说接口的大小,否则就没有接口可以满足。
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
typedef long long LL;
LL n, p , s;
LL dp[N][N];
struct Node
{
int w, v;
}a[N];
bool cmp(Node a, Node b)
{
if(a.w != b.w) return a.w < b.w;
else return a.v > b.v;
}
int BinarySearch()
{
int l = 1, r = n, mid = 0;
while(l < r)
{
mid = (l + r) / 2;
if(dp[mid][s] >= p) r = mid;
else l = mid + 1;
}
return l;
}
int main()
{
ios::sync_with_stdio(false);
freopen("cin.in", "r", stdin);
freopen("cout.out", "w", stdout);
cin >> n >> p >> s;
for(int i = 1; i <= n; i++)
cin >> a[i].w >> a[i].v;
sort(a + 1, a + n + 1, cmp);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= s; j++)
{
if(a[i].w <= j) dp[i][j] = max(dp[i-1][j], dp[i-1][j-a[i].w] + a[i].v);
else dp[i][j] = dp[i-1][j];
}
}
int pos = BinarySearch();
if(dp[pos][s] < p) cout << "No Solution!" << endl;
else cout << a[pos].w << endl;
return 0;
}
看了一波其他人的人,发现好像不用二分就行,找到第一个组合满足总价值是大于或者等于p即可.
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
typedef long long LL;
LL n, p , s;
LL dp[N][N];
struct Node
{
int w, v;
}a[N];
bool cmp(Node a, Node b)
{
if(a.w != b.w) return a.w < b.w;
else return a.v > b.v;
}
int main()
{
ios::sync_with_stdio(false);
//freopen("cin.in", "r", stdin);
//freopen("cout.out", "w", stdout);
cin >> n >> p >> s;
for(int i = 1; i <= n; i++)
cin >> a[i].w >> a[i].v;
sort(a + 1, a + n + 1, cmp);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= s; j++)
{
if(a[i].w <= j) dp[i][j] = max(dp[i-1][j], dp[i-1][j-a[i].w] + a[i].v);
else dp[i][j] = dp[i-1][j];
if(dp[i][s] >= p)
{
cout << a[i].w << endl;
return 0;
}
}
}
cout << "No Solution!" << endl;
return 0;
}

浙公网安备 33010602011771号