1. 程式人生 > >NYOJ 586 瘋牛 & POJ 2456(二分搜尋 + 貪心)(最大化最小值)

NYOJ 586 瘋牛 & POJ 2456(二分搜尋 + 貪心)(最大化最小值)

Aggressive cows
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8752 Accepted: 4349

Description

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000). 

His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?

Input

* Line 1: Two space-separated integers: N and C 

* Lines 2..N+1: Line i+1 contains an integer stall location, xi

Output

* Line 1: One integer: the largest minimum distance

Sample Input

5 3
1
2
8
4
9

Sample Output

3

Hint

OUTPUT DETAILS: 

FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3. 


Huge input data,scanf is recommended.

題意要表達的是:把C頭牛放到N個帶有編號的隔間裡,使得任意兩頭牛所在的隔間編號的最小差值最大。例如樣例排完序後變成1 2 4 8 9,那麼1位置放一頭牛,4位置放一頭牛,它們的差值為3;最後一頭牛放在8或9位置都可以,和4位置的差值分別為4、5,和1位置的差值分別為7和8,不比3小,所以最大的最小值為3。

分析:這是一個最小值最大化的問題。先對隔間編號從小到大排序,則最大距離不會超過兩端的兩頭牛之間的差值,最小值為0。所以我們可以通過二分列舉最小值來求。假設當前的最小值為x,如果判斷出最小差值為x時可以放下C頭牛,就先讓x變大再判斷;如果放不下,說明當前的x太大了,就先讓x變小然後再進行判斷。直到求出一個最大的x就是最終的答案。

本題的關鍵就在於討論差值的大小。

自己的程式碼:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#define M(i,n,m) for(int i = n;i < m;i ++)
#define N(n,m) memset(n,m,sizeof(n));
using namespace std;
const int MAX = 100010;
int a[MAX],n,m;
bool C(int d)///判斷是否滿足條件
{
    int last = 0;
    M(i,1,m)
    {
        int crt = last + 1;
        while(crt < n && a[crt] - a[last] < d)
            crt ++;
        if(crt == n)
            return false;
        last = crt;
    }
    return true;
}
void solve()
{
    int x = 0,y = a[n-1] - a[0];    ///分別找出此時對應的x和y的值
    while(y - x > 1)
    {
        int mid=(x+y)/2;
        if(C(mid))
            x=mid;
        else
            y=mid;
    }
    printf("%d\n",x);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        N(a,0);
        M(i,0,n)
        scanf("%d",&a[i]);
        sort(a,a+n);
        solve();
    }
    return 0;
}

貼上的程式碼:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
const int MAX = 100010;
int a[MAX],n,m;

bool C(int d)
{
    int t = a[0],count = 1;
    for(int i = 1;i < n;i ++)
    {
        if(a[i] - t >= d)
        {
            count ++;
            t=a[i];
            if(count >= m)
                return true;
        }
    }
    return false;
}


int solve()
{
    int x = 0,y = a[n-1] - a[0];
    while(x <= y)
    {
        int mid=(x+y)/2;
        if(C(mid))
            x=mid + 1;
        else
            y=mid - 1;
    }
    return x - 1;
}


int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i = 0;i < n;i ++)
        scanf("%d",&a[i]);
        sort(a,a+n);
        printf("%d\n",solve());
    }
    return 0;
}