ACM之路(1)——对二分及三分的研究

  对于二分来说,个人暂且将其分为整数型和实数型。
      对整数型而言,一般问题对于(low<=high)条件的判断取等号即可,因为在while途中查找遇到可匹配的便break,比方说二分查找已排序的数列。但是有些问题并不是这样的,在此分为两类:取最大值的min,和取最小值的max。
      对于前一种,要用<(即不断往下推得最优解),而后一种要用<=(即不断往上推得最优解)。同时,若对于前一种情况而言,因为要取最小的最优解,那么即使取中的mid可以满足条件仍要将high=mid-1以获得更小的最优解;对max的情况也是一样。
     下面给出两个例子以示说明:
     min型:

Description

Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and recorded the exact amount of money (1 ≤ moneyi ≤ 10,000) that he will need to spend each day over the next N (1 ≤ N ≤ 100,000) days.

FJ wants to create a budget for a sequential set of exactly M (1 ≤ M ≤ N) fiscal periods called "fajomonths". Each of these fajomonths contains a set of 1 or more consecutive days. Every day is contained in exactly one fajomonth.

FJ‘s goal is to arrange the fajomonths so as to minimize the expenses of the fajomonth with the highest spending and thus determine his monthly spending limit.

Input

Line 1: Two space-separated integers: N and M
Lines 2.. N+1: Line i+1 contains the number of dollars Farmer John spends on the ith day

Output

Line 1: The smallest possible monthly limit Farmer John can afford to live with.

Sample Input

7 5100400300100500101400

Sample Output

500

Hint

If Farmer John schedules the months so that the first two days are a month, the third and fourth are a month, and the last three are their own months, he spends at most $500 in any month. Any other method of scheduling gives a larger minimum monthly limit.

代码如下:

#include <stdio.h>

#include <string.h>

#include <algorithm>

using namespace std;

int a[100005];

int main()

{

int n,m,mid;

while(scanf("%d%d",&n,&m)==2)

{

int sum=0;

int maxn=-1;

int i;

for(i=1;i<=n;i++)

{

scanf("%d",&a[i]);

if(a[i]>maxn) maxn=a[i];

sum+=a[i];

}

mid=(maxn+sum)/2;

while(maxn<sum)   //注意这里是<!

{

int cnt=1;

int s=0;

for(i=1;i<=n;i++)

{

s+=a[i];

if(s>mid)

{

cnt++;

s=a[i];

}

}

if(cnt<=m) sum=mid-1;

else maxn=mid+1;

mid=(maxn+sum)/2;

}

printf("%d\n",mid);

}

return 0;

}

max型:

Description

Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).

To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.

Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up torocks (0 ≤ M ≤ N).

FJ wants to know exactly how much he can increase the shortest distance *before* he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.

Input

Line 1: Three space-separated integers: LN, and M
Lines 2.. N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.

Output

Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing M rocks

Sample Input

25 5 2214112117

Sample Output

4

Hint

Before removing any rocks, the shortest jump was a jump of 2 from 0 (the start) to 2. After removing the rocks at 2 and 14, the shortest required jump is a jump of 4 (from 17 to 21 or from 21 to 25).

代码如下:

#include<iostream>

#include<cstdlib>

#include<stdio.h>

#include<algorithm>

#include<math.h>

using namespace std;

int a[50000+5];

int main()

{

int l,n,m;

while(scanf("%d%d%d",&l,&n,&m)==3)

{

for(int i=1;i<=n;i++) scanf("%d",&a[i]);

a[0]=0;a[n+1]=l;

sort(a+1,a+1+n);

int minn=a[1]-a[0],maxx=l;

for(int i=1;i<=n+1;i++) minn=min(minn,a[i]-a[i-1]);

int mid=(minn+maxx)>>1;

while(minn<=maxx)  //注意这里是<=!

{

int cnt=-1;

int s=0;

for(int i=1;i<=n+1;i++)

{

s+=a[i]-a[i-1];

if(s>=mid)

{

cnt++;

s=0;

}

}

if(cnt<n-m) maxx=mid-1;

else minn=mid+1;

mid=(minn+maxx)>>1;

}

printf("%d\n",mid);

}

}

至于证明过程还是将中间变量都printf出来看看好了,之前都想破头脑才搞清楚的= =。

至于实数型的二分或三分只要设一个eps即可,用<就行(因为区间变化是取mid的,所以如果相等就会一直处于那个值出不来了。)
但是有一个问题,精度的问题,如2.005用%.2f输出是2.01,若想要结果是2.00,则可以这样写:
if((int)(high*1000)%10>=5) high-=0.005;
或者乘100用floor在除以100。
下面给一个例子:

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 312849

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.

代码如下:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define eps 1e-9
using namespace std;

double a[10005];
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
        double sum=0;
        for(int i=1;i<=n;i++) {scanf("%lf",&a[i]);sum+=a[i];}
        sum/=k;
        double low=0,high=sum,mid=(low+high)/2;
        while(low+eps<high)
        {
            //printf(" %f %f %f\n",low,high,mid);
            int cnt=0;
            for(int i=1;i<=n;i++)
            {
                cnt+=(int)(a[i]/mid);
            }
            if(cnt>=k) low=mid;
            else high=mid;
            mid=(low+high)/2;
        }
        if((int)(high*1000)%10>=5) high-=0.005;
        printf("%.2f\n",high);

}

时间: 2024-10-14 09:51:46

ACM之路(1)——对二分及三分的研究的相关文章

OUC&amp;&amp;我的ACM之路(三)

OUC && 我的ACM之路(三) 时间匆匆,转眼间,省赛我都已经参加过三届了.前面两篇日志:OUC && 我的ACM之路(一)  OUC && 我的ACM之路(二)首先吐槽一下这次省赛题目实在太简单了,也许HIT认为我们就这个水平吧.SD加油,早日冲出final.  rank在这里 其实我也没啥好总结的,只是感概,时间过得匆匆,很多话,前面两篇里面已经说了.最后说一下,实际比赛的时候,ABG三个数学题目,ouc_abc写的,Orz,要当时的状态,我应该是推

hrbust 1331 ACM之路 邂逅DP【dp】

ACM之路 邂逅DP Time Limit: 1000 MS Memory Limit: 65536 K Total Submit: 158(51 users) Total Accepted: 67(46 users) Rating: Special Judge: No Description MM迷上了ACM,不可救药... 算法绝非一天两天就能学好,需要不断的看书学习,不断的敲代码,不断的看书学习,不断的敲代码... 这是一条没有尽头的路... 尼玛的搞ACM的伤不起啊!!! 详情见:搞AC

二分与三分(精度类型)

二分:传送门 三分:传送门 (注意,是五舍六入,不是四舍五入,在2018年10月23日前是这样的) 话说一本通上不是有讲嘛,做法自己看吧...(但是我太弱了,精度版看不懂QWQ). 简单讲一下二分与三分吧. 二分:必须满足单调性: 非增或非减就叫单调性(如果就好几个数相同,一般会用二分来找第一个数或最后一个数). 我们用两个数字l与r来代表搜索范围,而mid代表中间的位置的值,来跳来跳去,看情况来写. 如这题 int l=1,r=n,mid,ans=0; while(l<=r) { mid=(l

二分与三分

(写的很早忘了发布了...)今天高二的学长学姐们进行了二分和三分的测试(又名一本通课后题测试),感觉这个好有意思~ 关于什么是二分,三分,先咕咕咕了,来看一道题. 灯泡:https://loj.ac/problem/10016 题意概述:给出$H,h,D$,求阴影的最长长度(包括地上的和墙上的). 有种初中数学的既视感. 解:设灯泡为$A$,人头为$B$,连接$AB$并延长,与地面的延长线交于点$C$. 于是就结束了...吗? 还有一种可能就是影子并没有到墙上去,但是影响不大,两个函数叠加起来还

【信息学奥赛一本通】Part1.2 基础算法-二分与三分

问题 A: [二分和三分]愤怒的牛 题目描述 农夫约翰建造了一座有n间牛舍的小屋,牛舍排在一条直线上,第i间牛舍在xi的位置,但是约翰的m头牛对小屋很不满意,因此经常互相攻击.约翰为了防止牛之间互相伤害,因此决定把每头牛都放在离其它牛尽可能远的牛舍.也就是要最大化最近的两头牛之间的距离. 牛们并不喜欢这种布局,而且几头牛放在一个隔间里,它们就要发生争斗.为了不让牛互相伤害.John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是多少呢? 输入 第一行用空格分

ACM : HDU 2899 Strange fuction 解题报告 -二分、三分

Strange fuction Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5933 Accepted Submission(s): 4194 Problem Description Now, here is a fuction: F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100) C

ACM:HDU 2199 Can you solve this equation? 解题报告 -二分、三分

Can you solve this equation? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 16281 Accepted Submission(s): 7206 Problem Description Now,given the equation 8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y,can

hdu 2899 凸性 二分 / 三分

Strange fuction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7230    Accepted Submission(s): 4996 Problem Description Now, here is a fuction:  F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=

剪辑的楼天城的ACM之路

楼天城楼教主的acm心路历程(剪辑) 利用假期空闲之时,将这几年GCJ,ACM,TopCoder 参加的一些重要比赛作个回顾.昨天是GCJ2006 的回忆,今天时间上更早一些吧,我现在还清晰记得3 年前,我刚刚参加ACM 时参加北京赛区2005 和杭州赛区2005 的情况.2005 年ACM-ICPC——酸甜苦辣我进入清华大学开始本科学习的时间是2004 年8 月,在进入清华大学的第一年里,由于基础课学习比较紧张,再加上计算机系不允许大一学生自带电脑,我没有参加2004 年的ACM 比赛.不过在