Binary search practice

Find a binary premise is that the array is ordered

1. The subscript binary search request

Write pictures described here

int binary(int a[], int size, int p)
{
    int low = 0;
    int high = size - 1;//左右端点
    int mid;
    while (low <= high)
    {
        mid = low + (high - low) / 2;
        if (p == a[mid])
            return mid;
        else if (p > a[mid])
            low = mid + 1;
        else
            high = mid - 1;
    }
    return -1;
}

2. Maximum and minimum requirements binary search
Write pictures described here

int low(int a[],int size, int p)
{
    int low = 0, high = size-1;
    int mid;
    while (low<=high)
    {
        mid = low + (high - low) / 2;
        if (a[mid] < p)//如果a[mid]<p时说明此时a[mid]小于p成立,但不一定是最优解,可能还有大于mid但比p小的数
            low = mid + 1;
        else
            high = mid - 1;
    }
    return low - 1;// 因为找到mid之后还会测试mid之后一个数,所以返回的数应该是low - 1;
}

3. Find the application binary

Mad Cow

Time limit: 1000 ms | Memory Limit: 65535 KB
Difficulty: 4
Description
Farmer John built a long corral, which includes N (2 <= N <= 100,000) compartments, these cubicles are numbered x1 , ..., xN (0 <= xi <= 1,000,000,000).
However, John's C (2 <= C <= N) cows who do not like the layout, and a few head of cattle in a compartment, they the battle will take place. To keep cattle hurt each other. John decided to allocate its own compartment to cattle, the minimum distance between any two cows as large as possible, then, what is the largest minimum distance is it?
Enter
multiple sets of test data, ending with an EOF.
The first line: two integers N and C separated by a space
of the second row - N + 1 th line: xi indicates the position of each
output of
the maximum output of each test a minimum integer satisfying meaning of the title, note wrap .
Sample input
. 5 3
. 1
2
. 8
. 4
. 9
sample output
3
that Italy:
total of n compartments, which have to occupy a cow c Niuquan separately. Q. largest minimum distance between these c cow.
Tip: Request is the largest minimum distance, you can find out the range of possible distance

#include<iostream>
#include<algorithm>
using namespace std;
int n, c, a[100005];
bool judge(int mid)
{
    int num = 1;//假设已经放了一头牛
    int pre = a[0];//pre是前一个牛舍的编号,根据贪心思想第一间牛舍应该放一头牛
    for (int i = 1; i < n; i++)  //依据牛舍进行判断
    {
        if (a[i] - pre >= mid)//如果a[i]-前一个牛舍编号大于等于mid,则在a[mid]牛舍放入一头牛,num++
        {
            num++;
            pre = a[i];//将前一个放牛的牛舍编号改为a[i];
            if (num >= c)return true;//如果可以放入的牛数量大于等于总牛数量,那么证明此mid可行,返回true
        }
    }
    return false;
}

/*        暂时不知道为什么不对
bool judge(int mid)
{
    int pre = a[0];
    for (int i = 1; i < c; i++)
    {

        int j = 1;//牛舍
        while (a[j] - pre<mid)
        {
            j++; // 1 2 4 8 9
            if (j>n - 1)  return false;
        }
        pre = a[j];
    }

*/
int main()
{
    while (~scanf("%d %d", &n, &c))
    {
        for (int i = 0; i < n; i++)
            cin >> a[i];
        sort(a, a + n);

        int low = 0, high = a[n - 1] - a[0];//确定牛舍之间可能的范围
        int mid;
        while (low <= high)
        {
            mid = low + (high - low) / 2;
            if (judge(mid))   
                low = mid + 1;
            else
                high = mid - 1;

        }
        cout << low - 1 << endl;
    }

    return 0;
}

01:派
描述
我的生日要到了!根据习俗,我需要将一些派分给大家。我有N个不同口味、不同大小的派。有F个朋友会来参加我的派对,每个人会拿到一块派(必须一个派的一块,不能由几个派的小块拼成;可以是一整个派)。

我的朋友们都特别小气,如果有人拿到更大的一块,就会开始抱怨。因此所有人拿到的派是同样大小的(但不需要是同样形状的),虽然这样有些派会被浪费,但总比搞砸整个派对好。当然,我也要给自己留一块,而这一块也要和其他人的同样大小。

请问我们每个人拿到的派最大是多少?每个派都是一个高为1,半径不等的圆柱体。

输入
第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示派的数量和朋友的数量。
第二行包含N个1到10000之间的整数,表示每个派的半径。
输出
输出每个人能得到的最大的派的体积,精确到小数点后三位。
样例输入
3 3
4 3 3
样例输出
25.133

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
double pi = 3.14159265358979323846;
int n, f;
double s[10005];//存储每个派的体积
bool judge(double mid)
{
    int num = 0;//记录所能分得所有的派的数量,初始化为零
    for (int i = 0; i<n; i++)//记录在体积为mid时,每个派所能分得数量
    {
        num += int(s[i] / (mid * 1000000));
    }
    if (num >= f + 1) return true;//如果当体积为mid时所分的数量大于等于总人数(f+1)时就是这种方案可以保证每人都有,返回true
    else return false;
}
int main()
{
    scanf("%d %d", &n, &f);
    for (int i = 0; i<n; i++)
    {
        double r;
        cin >> r;
        s[i] = pi*r*r * 1000000;//乘1000000是为了使小数点后移,保证精确度
    }
    sort(s, s + n);

    ////二分查找,是要求其最小的最大体积,所以要确定提及可能的变化范围
    double low = 0, high = s[n - 1], mid;//变化范围为0--s【n-1】
    while (high>=low)
    {
        mid = low + (high - low) / 2;

        if (judge(mid))  //如果当mid符合时则继续对low后移,因为此时的mid符合但不一定是最优解
            low = mid + 0.00001;
        else high = mid - 0.00001;
    }
    printf("%.3lf", mid);
    return 0;
}

02:河中跳房子

描述
每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一个岩石跳到另一个岩石。这项激动人心的活动在一条长长的笔直河道中进行,在起点和离起点L远 (1 ≤ L≤ 1,000,000,000) 的终点处均有一个岩石。在起点和终点之间,有N (0 ≤ N ≤ 50,000) 个岩石,每个岩石与起点的距离分别为Di (0 < Di < L)。

在比赛过程中,奶牛轮流从起点出发,尝试到达终点,每一步只能从一个岩石跳到另一个岩石。当然,实力不济的奶牛是没有办法完成目标的。

农夫约翰为他的奶牛们感到自豪并且年年都观看了这项比赛。但随着时间的推移,看着其他农夫的胆小奶牛们在相距很近的岩石之间缓慢前行,他感到非常厌烦。他计划移走一些岩石,使得从起点到终点的过程中,最短的跳跃距离最长。他可以移走除起点和终点外的至多M (0 ≤ M ≤ N) 个岩石。

请帮助约翰确定移走这些岩石后,最长可能的最短跳跃距离是多少?

输入
第一行包含三个整数L, N, M,相邻两个整数之间用单个空格隔开。
接下来N行,每行一个整数,表示每个岩石与起点的距离。岩石按与起点距离从近到远给出,且不会有两个岩石出现在同一个位置。
输出
一个整数,最长可能的最短跳跃距离。
样例输入
25 5 2
2
11
14
17
21
样例输出
4
提示
在移除位于2和14的两个岩石之后,最短跳跃距离为4(从17到21或从21到25)。

#include<iostream>
#include<algorithm>
using namespace std;
int L, n, m;
int a[50002];
int judge(int mid)
{
    int num = 0;//记录所去除的石头数量
    int pre = 0;//pre表示前一石头距离岸边的距离
    for (int i = 1; i <= n; i++)
    {
        if (a[i] - pre < mid)
        {
            num++;
            if (num>m) return 0;
        }
        else
        {
            pre = a[i];
        }

    }
    return 1;
}
int main()
{
    scanf("%d %d %d", &L, &n, &m);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    a[++n] = L;//还要把终点距离起点的距离
    sort(a + 1, a + n + 1);
    int low = 0, high = L;//确定石头之间距离可能的范围
    int mid;
    while (low <= high)
    {
        mid = low + (high - low) / 2;
        if (judge(mid))
            low = mid + 1;
        else
            high = mid - 1;
    }
    cout << low - 1 << endl;
}

总结:
个人认为,二分法求解最大的最小值时,二分的是题目需要求的范围,例如派的体积、石头之间的距离、牛舍之间的距离……

if (a[mid] < p)//如果a[mid]<p时说明此时a[mid]小于p成立,但不一定是最优解,可能还有大于mid但比p小的数
            low = mid + 1;
        else
            high = mid - 1;

上方代码low=mid+1,是要尝试下一个值是不是最优解,因为if(a[mid]<屁)成立,只能证明mid可以满足条件,但并不代表就是最大的最小值,所以要继续向后逼近(因为数组a是经过排序的);

发布了24 篇原创文章 · 获赞 5 · 访问量 3958

Guess you like

Origin blog.csdn.net/qq_41345281/article/details/81485335