洛谷P2370 yyy2015c01 的 U 盘 二分答案+背包
很简单但是很有意思的一道题
题意:
n个文件,最小价值p,硬盘大小为s
设端口大小为每次传输文件大小的上限
求最少需要多大的端口可以传过去价值总和大于等于p的文件
如果没有则输出No Solution!
思路:
因为端口大小具有单调性,所以可以二分
对端口大小进行二分,check函数中进行01背包,判断能否装下价值总和大于等于p的文件即可
如果大小等于右端点也装不下,则无解
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n, p, s;
int dp[1005][1005];
int wei[1005];
int val[1005];
bool check(int x) {
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= s; j++) {
if (wei[i] <= x) {
if (j >= wei[i]) {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - wei[i]] + val[i]);
}
else {
dp[i][j] = dp[i - 1][j];
}
}
else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[n][s] >= p;
}
int main(void) {
scanf("%d%d%d", &n, &p, &s);
int l = 1, r = 1;
for (int i = 1; i <= n; i++) {
scanf("%d%d", wei + i, val + i);
r = max(r, wei[i]);
}
int m;
if (!check(r)) {
printf("No Solution!");
return 0;
}
while (l<=r)
{
m = (l + r) >> 1;
if (check(m)) {
r = m - 1;
}
else {
l = m + 1;
}
}
printf("%d", l);
return 0;
}