タイトル説明:
農夫ジョンはN(2 <= N <= 100,000)の区画を持つブルペンを作りました。これらの区画は直線に分布し、座標はx1、...、xN(0 <= xi <= 1,000,000,000)です。
彼のC(2 <= C <= N)牛はコンパートメントの位置に不満を持っており、ブルペンに他の牛がいることに腹を立てています。牛同士の戦いを防ぐために、ファーマージョンはこれらの牛を指定された区画に配置したいと考えています。隣接する2頭の牛の間の距離が大きいほど良いです。それで、最大の最も近い距離は何ですか?
入る:
1行目:スペースで区切られた2つの数値NとC。
2〜N + 1行目:1行あたりの整数は、各コンパートメントの座標を表します。
出力:
出力は1行のみです。つまり、隣接する2頭の牛の間の最短距離が最大になります。
アイデア:
最大の最短距離を見ると、明らかに二分法を使用する必要があります。この質問の方法は、石のジャンプの問題の方法とまったく同じです。石の二分法をジャンプする方法。
- 最初にブルペンの座標を並べ替えてから、2つに分割します。現在の解がmidであると仮定すると、判定関数はmidが実行可能解であるかどうかを判断します。実行可能解である場合は、右に移動してより良い解を探します。実行可能な解決策でない場合は、左に移動して検索します
- 最も重要なのは、その解がxの実行可能解であるかどうかを判断し、xを解として使用して、何頭の牛を配置できるかを決定する判定関数、judge(x)です。が指定された牛の数以上の場合、直接trueを返します。xを最小距離とすると、配置できる牛の数が指定された数以上になり、より多くの牛を取り除くことができます。最小のものを保持できます。トラバーサルが指定された数以下の場合、falseが返され、これは違法な解決策であることを示します
コード:
#include <iostream>
#include <algorithm>
using namespace std;
int n,c,l,r,mid,ans;
int a[100005];
bool judge(int x)//x为当前二分的解,判断是否合法
{
int sum=1;//可以放的奶牛数量
int now=1;//当前所在的位置
for(int i=2;i<=n;i++)//第一个位置放一头牛,从第二个位置开始
{
if(a[i]-a[now]>=x)//两头奶牛之间距离大于x,就在这个地方放奶牛
{
sum++;
now=i;
}
if(sum>=c) //已经放的奶牛数量大于等于有的奶牛,就是可行解
return true;
}
return false;//遍历结束,奶牛数量还不够,就是非法解
}
int main()
{
cin>>n>>c;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
l=1;
r=a[n]-a[1];
while(l<=r)
{
mid=(l+r)/2;
if(judge(mid))//判断当前解是否为可行解
{
l=mid+1;//如果mid是可行解,那么右边可能会有更优的解
ans=mid;
}else
r=mid-1;//mid不是可行解,那么就去左边寻找
}
cout<<ans<<endl;
return 0;
}