挑战上面讲的很全了,自己实现了一遍,在做个总结。
一些注意:
- 最后实在不知道输出mid left 还是right,就把mid mid+1 mid-1根据特定的顺序都判断一遍就不会出错。
一:二分查找值
普通的二分。
二:假定一个解并判断是否可行。
1:切小木棍
//最经典的就是从n个小木棍里面切除k个最长的,求出最长的长度。
//http://222.22.65.164/problem.php?id=4245题目链接
//有两种写法,一种是取mid100次,另一种是卡r-l>=1e9等,但是不要卡的太小,会陷入死循环
//输出一定是用r而不是mid因为r一定>=mid,向下取整的时候,r一定可以,但是mid就不一定了。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4;
double len[maxn];
int n,k;
bool isleft(double mid)
{
int ans=0;
for(int i=1;i<=n&&len[i]>=mid;i++)
ans+=len[i]/mid;
if(ans>=k) return false;
else return true;
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
scanf("%lf",&len[i]);
sort(len+1,len+n+1,greater<double>());
double l=0,r=2*len[1],mid;
for(int i=1;i<100;i++){
mid=(l+r)/(double)2;
if(isleft(mid)) r=mid;
else l=mid;
}
printf("%.2lf",floor(r*100)/(double)100);
// do{
// mid=(l+r)/(double)2;
// if(isleft(mid)) r=mid;
// else l=mid;
// }while(r-l>1e-9);
// printf("%.2lf",floor(r*100)/(double)100);
return 0;
}
2:
三:最小值的最大值(洛谷跳石子问题)
https://www.luogu.org/problemnew/show/P2678
#include <bits/stdc++.h>
using namespace std;
const int maxn=50005;
int L,N,M;
int pos[maxn];
bool judge(int len)
{
int ans=0;
int beg=0;
for(int i=2;i<=N+1;i++){
while(pos[i]<beg+len&&i<=N+1){
ans++;
i++;
}
beg=pos[i];
if(ans>M) break;
}
if(ans>M) return true;
else return false;
}
int main()
{
cin>>L>>N>>M;
for(int i=2;i<=N+1;i++)
scanf("%d",&pos[i]);
pos[1]=0,pos[N+2]=L;
int l=0,r=L,mid;
while(l<r)
{
mid=(l+r)/2;
if(judge(mid)) r=mid-1;
else l=mid+1;
}
int ans;//最后一步搞得有些流氓了。。。但是在拿不准选哪个。
if(!judge(mid+1)) ans=mid+1;
else if((!judge(mid))) ans=mid;
else ans=mid-1;
printf("%d",ans);
return 0;
}
四:求平均值的最大值
这一类的问题很容易被当成贪心。
有n个重wi 价值为vi的物品,从中选取k个,让他们总单位体积的价值最大。这可不是贪心啊