传送门——P2370 yyy2015c01 的 U 盘
题解:题目意思很好理解,就是说,当能够达到预期的U盘的最小接口(接口越大,能传递的文件越大),然后我们就需要先看题目了,有n个文件,每个文件有其自己的重量和价值,我们的U盘最多就只能装S大小的文件,因此我们很容易就想到了01背包,但是和01背包不同的地方就我们会有一个对文件重量的限制,不允许超过L,那我们该如何去得到这个最小的L呢,我们不难想到二分答案,我们对文件的大小进行排序,然后二分,如果算出来的价值小了,就向右取,如果价值大于预期,就向左取,然后循环往复,用ans去记录能够达到预期的的最小的接口大小L
注意:每次进行二分操作的时候都要重新初始化dp数组,还有就是在进行01背包的时候需要对文件的大小进行筛选,大于接口大小的都要去跳过
//二分答案枚举文件大小,价值就将接口减小,小于价值就将接口增大 #include<bits/stdc++.h>
using namespace std;
#define int long long
int n,p,s;
struct node
{int w;int v;
}a[1005];
int dp[1005];//表示大小为j内存的u盘能保留的最大价值
int L;//限制传送的最大文件
int ans;//用来记录可行的数值
bool cmp(node a,node b)
{return a.w<b.w;
}signed main()
{cin>>n>>p>>s;for(int i=1;i<=n;i++){cin>>a[i].w>>a[i].v;}sort(a+1,a+1+n,cmp);int l=1,r=n;int mid=0;int flag=0;while(l<=r){memset(dp,0,sizeof(dp));mid=(l+r)>>1;L=a[mid].w;for(int i=1;i<=n;i++){if(a[i].w>L)continue;for(int j=s;j>=a[i].w;j--){dp[j]=max(dp[j],dp[j-a[i].w]+a[i].v);}}if(dp[s]>=p){ans=L;r=mid-1;flag=1;}else{l=mid+1;}}if(flag==0){cout<<"No Solution!";return 0;}cout<<ans;return 0;
}