1433:【例题1】愤怒的牛
题解
This is an er‘fen ti.
由题意可得 它是求最小值最大的问题
我们假设:
每两头牛之间的最小距离为 d ,也就是每两头牛之间的距离 >= d ,问题也就是求这个 d 最大是多少
理一理思路:
1.对所有的牛舍从小到大排序
2.假设我们把第 i 头牛放在 ai 号牛舍里,那么第 i+1 头牛就要放在 ai+d<=ak 的ak 牛舍中,由于可能有很多牛舍满足条件,我们选取距离 ai 最近的一个(这是很显然的),然后依次类推,放牛, 放牛,放牛。。。
Ps:解释一下为什么显然:
按照思路,我们应该把cow2放在4号,但是我们就不,我们看看会有什么后果
好啦,显然,我们应该按照思路走:选取距离 ai 最近的一个
3.由于只需要在开头对数组进行一次sort排序,后面每次判断对每头牛只需要进行一次处理,时间复杂度为O(nlogn)
(注释在代码后面o)
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> using namespace std; const int maxn=1e5+1; int n,c; int a[maxn]; bool check(int d) //注释5 { int cow=1; int now=a[1]+d; for(int i=2;i<=n;i++) { if(a[i]<now) continue; cow++; now=a[i]+d; } return cow>=c; } int main() { scanf("%d%d",&n,&c); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); //注释1 int l=0,r=a[n]-a[1]; //注释2 while(l<=r) { int mid=(l+r)>>1; //注释3 if(check(mid)) l=mid+1; //注释4 else r=mid-1; } printf("%d",r); return 0; }
注释
1.输入数据,然后排序一下牛舍
2.初始化一下 L 为0,r 其实就是最后的结果,初始化为第一个牛舍与最后一个牛舍的距离
3.mid为暂定的那个最小距离(也就是博客开始的那个 d ),二分常规操作,(l+r)÷2
4.拿着mid去函数check里看一看(建议结合一下注释5看check的用法)
(1)最小距离定为这个mid,cow可以放下的数目>=规定数目,那么说明这个mid可以再大一点, 更新 l
(2)最小距离定位这个mid,牛舍不能放下约翰的牛喽,那就说明这个距离就要缩小一点啦,更新 r
5.自定义check函数
(1)我们放了第一个cow
(2)下一个cow就要放到>=的牛舍里距离上一个cow最近的牛舍中了
(3)for循环,计算可以放入cow的数目
(4)返回的数值用于注释4
6.不断二分啊二分啊,l 就无限逼近 r ,最后就得到答案啦
原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/10989190.html