小码哥剪绳子
题目描述
![](https://img-blog.csdnimg.cn/img_convert/4e71d1085dccc7f98c0fb33b57fa9f5e.png)
![](https://img-blog.csdnimg.cn/img_convert/d1c491fa94064aaeeb62d8018e8ad0a6.png)
![](https://img-blog.csdnimg.cn/img_convert/aa1b28852040a4b1445a91e713952e78.png)
解题思路
设可能的最大长度上界为right, 下界为left,不断取出中间长度mid,根据是否可以分出k条mid长度的绳子,对区间进行二分。时间复杂度O(nlogL)。
代码
#include<bits/stdc++.h>
using namespace std;
// typedef long long ll;
int main ( )
{
// freopen("input.txt","r",stdin);
int n,k,left=0,right=0;
cin>>n>>k;
vector<int> len(n);
for(int i=0;i<n;++i){
cin>>len[i];
right=max(right,len[i]);
}
while(left<right){//left==right时,答案一定是left,不用再探查
int mid=(left+right+1)/2,cnt=0;//mid如此取值,为了避免left一直等于mid,死循环
for(int i=0;i<n;++i){
cnt+=len[i]/mid;
if(cnt>=k){
break;
}
}
if(cnt>=k){
left=mid;
}
else{
right=mid-1;
}
}
cout<<left<<endl;
}
咖啡品鉴师小码哥
题目描述
![](https://img-blog.csdnimg.cn/img_convert/d6d29faef5ebf2980eb3b37f51b46650.png)
![](https://img-blog.csdnimg.cn/img_convert/928939dbcba662c7066792a40df6d000.png)
![](https://img-blog.csdnimg.cn/img_convert/3742cf069d210813034b918edaf61ee9.png)
解题思路
误区提醒SOS:定义个体性价比vi/ci,整体性价比Σvi/Σci,使得整体性价比最高的m项不一定取自个体性价比最高的m项。参考反例:v1=3, c1=1, v2=101, c2=100, v3=1, c3=1, m=2。
思路依然是二分。每次取可行区间中点值mid,欲判断Σvi/Σci>=mid,即Σ(vi-ci*mid)>=0。我们构造数组ti=vi-ci*mid,对该数组排序,取最大的m项,判断加和是否大于等于0即可。
这题的特别之处是对实数进行二分,因此循环终止条件为right-left<eps。
代码
#include<bits/stdc++.h>
using namespace std;
// typedef long long ll;
const double eps=1e-6;
bool check(double mid,vector<int>& v, vector<int>& c,int m){
int n=v.size();
vector<double> t(n);
for(int i=0;i<n;++i){
t[i]=v[i]-c[i]*mid;
}
sort(t.begin(),t.begin()+n,greater<int>());
double sum=0;
for(int i=0;i<m;++i){
sum+=t[i];
}
if(sum>-eps){
return true;
}
return false;
}
int main ( )
{
// freopen("input.txt","r",stdin);
int n,m;
cin>>n>>m;
vector<int> v(n),c(n);
double left=0,right=0;
for(int i=0;i<n;++i){
cin>>v[i];
}
for(int i=0;i<n;++i){
cin>>c[i];
right=max(right,1.0*v[i]/c[i])+eps;
}
while(right-left>eps){
double mid=(left+right)/2;
if(check(mid,v,c,m)){
left=mid;
}
else{
right=mid;
}
}
printf("%.3lf",left);
return 0;
}