持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
yyy2015c01 的 U 盘
题目背景
在 2020 年的某一天,我们的 yyy2015c01 买了个高端 U 盘。
题目描述
你找 yyy2015c01 借到了这个高端的 U 盘,拷贝一些重要资料,但是你发现这个 U 盘有一些问题:
- 这个 U 盘的传输接口很小,只能传输大小不超过 的文件。
- 这个 U 盘容量很小,一共只能装不超过 的文件。
但是你要备份的资料却有很多,你只能备份其中的一部分。
为了选择要备份哪些文件,你给所有文件设置了一个价值 ,你希望备份的文件总价值不小于 。
但是很快你发现这是不可能的,因为 yyy2015c01 的传输接口太小了,你只有花钱买一个更大的接口(更大的接口意味着可以传输更大的文件,但是购买它会花费更多的钱)。
注意:你的文件不能被分割(你只能把一个文件整个的传输进去,并储存在U盘中),
你放在 U 盘中文件的总大小不能超过 U 盘容量。
现在问题来了:你想知道,在满足 U 盘中文件价值之和不小于 时,最小需要多大的接口。
输入格式
第 行,三个正整数 分别表示文件总数,希望最小价值 ,U 盘大小。
接下来 行,每行两个正整数 ,表示第 个文件的大小和价值。
输出格式
输出一个正整数表示最小需要的接口大小。
如果无解输出 No Solution!。
样例 #1
样例输入 #1
3 3 5
2 2
1 2
3 2
样例输出 #1
2
样例 #2
样例输入 #2
2 3 505
1 2
500 1
样例输出 #2
500
样例 #3
样例输入 #3
3 3 2
2 2
1 2
3 2
样例输出 #3
No Solution!
样例 #4
样例输入 #4
4 5 6
5 1
5 2
5 3
1 1
样例输出 #4
No Solution!
提示
,,。
数据较小,请勿乱搞。
样例解释 :买一个大小为 接口,把物品 、 放进盘。
样例解释 :买一个大小为 的接口。
样例解释 :本来可以买大小为 的接口,可是 U 盘容量放不下足够的文件。
如果数据出现疏漏,请联系出题人 a710128
向本题主人公 yyy2015c01 同学致敬!
分析
这题是个经典的二分+,有个要注意的地方,传输大小不超过的文件的意思是所有不超过的文件都可以传输,而不是只能传输一个(雾)。然后就是个典型的背包问题,就是大小为的背包最多能装多少价值的物品,然后要注意要特判一下,只有小于的物品才能装进背包。然后就二分一下接口的,找出最小的L,当最大的都无法满足的时候,说明无解。然后就没了。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <iomanip>
#define ll long long
#define AC return
#define Please 0
#define lowbit(x) x&(-x)
using namespace std;
const int N=1010;
typedef pair<int,int>PII;
typedef unsigned long long ull;
struct ob{
int w,v;
}a[N];
int dp[N];
inline int read(){//快读
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
AC x*f;
}
int w[N],v[N];//w文件大小 v文件价值
int n,p,s;//n数量 p总价值 s u盘容量
bool check(int x){
memset(dp,0,sizeof dp);
for(int i=1;i<=n;i++){
for(int j=s;j>=a[i].w;j--){
if(a[i].w<=x){
dp[j]=max(dp[j],dp[j-a[i].w]+a[i].v);
}
}
}
if(dp[s]>=p) return true;
return false;
}
int main(){
cin>>n>>p>>s;
int maxn=0;
for(int i=1;i<=n;i++){
cin>>a[i].w>>a[i].v;
maxn=max(maxn,a[i].w);
}
int l=0,r=maxn;
if(!check(maxn)){
cout<<"No Solution!"<<endl;
return 0;
}
while(l<r){
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l;
AC Please;
}
希望能帮到大家()!