【算法】题目分析:Aggressive Cow (POJ 2456)
题目信息
作者:不详
链接:http://poj.org/problem?id=2456
来源:PKU JudgeOnline
Aggressive cows[1]
Time Limit: 1000MS
Memory Limit: 65536K
描述
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?
输入
- Line 1: Two space-separated integers: N and C
 - Lines 2..N+1: Line i+1 contains an integer stall location, xi
 
输出
- Line 1: One integer: the largest minimum distance
 
样例输入
5 3
1
2
8
4
9
样例输出
3
提示
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.
题目解读与分析
(如果您已熟练掌握二分搜索,可以跳过本段与下一段,直接浏览代码)
- 这是一个搜索问题,适宜使用二分搜索
 
首先观察样例输入,输入的牛棚坐标不一定有序,反手一个快速排序,闷声发大财(逃
题目的意图是,给定一系列正整数  ,最大化其中任意 
 个数中两两之差的最小值(以下用 D 表示)。能不能直接利用输入的数据计算出这个“最大的最小值”呢?以我浅薄的智慧想不到可行的解决方案。相比起来,通过多次试探找出合理的 D 无疑更有可操作性。因此,这是一个搜索问题,或者至少将其当做一个搜索问题来对待。
- 为什么采用二分搜索?
 
现在我们需要在1~  之间试出一个满足题意的 D 。
最简单粗暴的方法就是从 开始降序验证 D 是否可行,并输出第一个可行的 D,但是这样的线性搜索太慢了。输入n个牛棚的坐标,最大的计算次数就是 
 ,约等于 
 次,会超时。所以需要使用二分搜索。
- 怎么验证一个D是否可行?
 
如何确定一个D是否可行呢?我们只要把第一头牛放在第一个牛棚里,把第二头牛放在 D 距离以外第一个遇到的牛棚,以此类推,最后看一看能不能放得下所有的牛。显然,D 有个不可逾越的上界,就是假设所有牛在总长度上(最右牛棚 - 最左牛棚)均匀分布时的间距,这个值就是  。
二分搜索
- 如何通过二分搜索寻找最优解?
对区间[ L, R ],当中间值mid不可行时,所有比mid大的D都不可行,右界左移开始下一轮;当mid可行时,不能确定mid右侧是否还有更大的可行解,因此用一个变量暂存当前可行解,然后左界右移,开始下一轮。当二分循环结束时,暂存的可行解即为所求最优解。 - 初始右界的确定
#——#——#——#——#——#
0——1——2——3——4——5
根据植树原理,右边界,即均匀分布时的距离,等于总长度(牛的头数 - 1)
 - 边界的移动
左边界右移时,如果将left更新为mid,当left与right相差1时,mid = (left + right) / 2的值总等于left,会引起死循环,所以应该将left更新为mid+1
由于数组是升序的,右边界左移时,不需考虑。想一想,这是为什么? 
- 如何通过二分搜索寻找最优解?
 
细节说明
- 输入方式
题目中提到“Huge input data,scanf is recommended.”,因此使用scanf_s而不是cin输入 - 命名与程序结构
为了增加程序的可读性、可修改性,可以将所有变量与函数都用英文单词(一些含义明确的局部变量除外)命名,并且将二分搜索的过程、验证最小距离D可行性的过程,抽象为函数。详见参考题解 - 排序
除非题目要求或有特殊需求,否则应尽量使用内置的排序。一般来说,语言、编译器提供的排序算法更安全、更高效 
参考题解
完整代码如下,仅供参考
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
//global
const int MAX_N = 100000;
const int MAX_STALL = 1000000000;
int N = 0,C = 1;
int stall[MAX_N] = {0};
//prototype
bool IsDOK(int D);
int SearchLargestMinDistance(int left, int right);
int cmpInt(const void * a, const void * b);
void Init();
int main()
{
    Init();
    int L = 1, R = (stall[N-1] - stall[0]) / (C - 1);
    int result = SearchLargestMinDistance(L, R);
    cout << result;
    return 0;
}
void Init()
{
    //input boundary data
    cin >> N >> C;
    //error check
    if(N > MAX_N || N < C || C < 2)
    {
        cout << "Input error! Out of range." << endl;
        exit(-1);
    }
    //input stall data and sort it
    for(int i = 0;i<N;i++)
    {
        scanf_s("%d",&stall[i]);
        if(stall[i] > MAX_STALL || stall[i] < 0)
        {
            cout << "Input error! Out of range." << endl;
            exit(-1);
        }
    }
    qsort(stall, N, sizeof(int), cmpInt);
}
int SearchLargestMinDistance(int left, int right)
{
    //init
    int mid = (left + right) / 2;
    int result = 0;
    //binary search
    while(right - left >= 0)
    {
        if(IsDOK(mid))
        {
            left = mid + 1;
            result = mid;
        }
        else
        {
            right = mid - 1;
        }
        mid = (left + right) / 2;
    }
    return result;
}
bool IsDOK(int D)
{
    //init
    int i = 0,p = stall[0];
    int restCow = C - 1;
    for(i = 1;i<N;i++)
    {
        if(stall[i] >= p + D)
        {
            p = stall[i];
            restCow--;
        }
    }
    return restCow <= 0;
}
int cmpInt(const void * a, const void * b)
{
    return ( *(int*)a - *(int*)b );
}
参考
- Aggressive cows http://poj.org/problem?id=2456
 
【算法】题目分析:Aggressive Cow (POJ 2456)的更多相关文章
- Divide and conquer:Aggressive Cows(POJ 2456)
		
侵略性的牛 题目大意:C头牛最大化他们的最短距离 常规题,二分法即可 #include <iostream> #include <algorithm> #include < ...
 - Aggressive cows(POJ 2456)
		
原题如下: Aggressive cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 20524 Accepted: ...
 - POJ 2456 Aggressive cows (二分 基础)
		
Aggressive cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7924 Accepted: 3959 D ...
 - poj 2456 Aggressive cows && nyoj 疯牛 最大化最小值 二分
		
poj 2456 Aggressive cows && nyoj 疯牛 最大化最小值 二分 题目链接: nyoj : http://acm.nyist.net/JudgeOnline/ ...
 - [poj 2456] Aggressive cows 二分
		
Description Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stal ...
 - 二分搜索 POJ 2456 Aggressive cows
		
题目传送门 /* 二分搜索:搜索安排最近牛的距离不小于d */ #include <cstdio> #include <algorithm> #include <cmat ...
 - POJ 2456 Aggressive cows (二分)
		
题目传送门 POJ 2456 Description Farmer John has built a new long barn, with N (2 <= N <= 100,000) s ...
 - [POJ] 2456 Aggressive cows (二分查找)
		
题目地址:http://poj.org/problem?id=2456 最大化最小值问题.二分牛之间的间距,然后验证. #include<cstdio> #include<iostr ...
 - POJ 2456 Aggressive cows---二分搜索法
		
///3.最大化最小值 /** POJ 2456 Aggressive cows Q:一排牛舍有N (2 <= N <= 100,000) 个,位置为x1,...,xN (0 <= ...
 
随机推荐
- Python中的错误和异常
			
前言 错误是程序中的问题,由于这些问题而导致程序停止执行.另一方面,当某些内部事件发生时,会引发异常,从而改变程序的正常流程. python中会发生两种类型的错误. 语法错误 逻辑错误(异常) 语法错 ...
 - 数据解析_bs进行数据解析
			
1.bs4进行数据解析 数据解析的原理 1.标签定位 2.提取标签,标签属性中存储的数据值 bs4数据解析的原理 1.实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中 2.通 ...
 - flask的小错误
			
这几天刚学flask,根据录屏学代码的时候,遇到一个问题 基本能看懂错误,role_id是类的一个字段,应该是一个对象,最后发现是单词写错了,应该是大写的Column, db.Column(db.In ...
 - pandas 模拟生成数据集的快速方法
			
快速生成一个DataFrame的方法: #模拟生成数据集的方法 import pandas as pd import numpy as np boolean=[True,False] gender=[ ...
 - 巧用transform: scale()
			
巧用transform: scale() 移动端font-size小于12px时line-height问题 由于出现的场景是字体小于12px的时候,所以可以将原来包括 font-size 在内的属性放 ...
 - RESTful API 规范(一)
			
一,简介 DRF 即Django rest framework 二,rest 规范 1 协议 API 与用户通信,总是使用https协议 2 域名 1) 应尽量将API 部署在域名下(这种情况会存在跨 ...
 - 仅需5步,轻松升级K3s集群!
			
Rancher 2.4是Rancher目前最新的版本,在这一版本中你可以通过Rancher UI对K3s集群进行升级管理. K3s是一个轻量级Kubernetes发行版,借助它你可以几分钟之内设置你的 ...
 - CVE-2020-5902 F5 BIG-IP 远程代码执行漏洞
			
CVE-2020-5902 F5 BIG-IP 远程代码执行漏洞复现 漏洞介绍 F5 BIG-IP 是美国 F5 公司的一款集成了网络流量管理.应用程序安全管理.负载均衡等功能的应用交付平台. 近日, ...
 - java学习第四天7/9
			
一. 今天学习了一些算法: 求最小值,最大值,平均值 接着学了几种排序方法 1.冒泡排序 (1)逐一比较数组中响铃的两个元素,如果后面的数字小于前面的数字,就交换先后元素: (2)经过一个轮次的比较, ...
 - 数据可视化之DAX篇(十一)Power BI度量值不能作为坐标轴?这个解决思路送给你
			
https://zhuanlan.zhihu.com/p/79522456 对于PowerBI使用者而言,经常碰到的一个问题是,想把度量值放到坐标轴上,却发现无法实现.尤其是初学者,更是习惯性的想这么 ...