2017级算法模拟上机准备篇(二分+贪心)

GRH:【 我这么喜欢复用曾经题目 然后揉起来的人……你们居然还没套路起来 】

计网的烦恼(一维覆盖问题)

由题目我们可以知道,答案一定在[l,pl[n]−pl[1]+1][l,pl[n]pl[1]+1]中,所以我们可以二分答案。

通过枚举每一个答案然后判断这个答案合不合理。

在这个题目中,如果我们发现答案可以cover所有的地方,那么我们就要去寻找更小的答案,如果发现无法cover,我们就去寻找更大的答案。

至于是否可以cover可以使用到贪心的思路,如果一个点无法被覆盖,那么就选取给定长度区间的左端点与该点重合进行覆盖。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MaxSize 100005
using namespace std;
int n, m;
int A[MaxSize], B[MaxSize];
bool judge(double t)
{
    int temp = A[0];
    int num = 1;
    for(int i = 1; i < n; i++){
        if(A[i]-temp > t * 2)
            {
                ++num;
                temp = A[i];
            }
        else
            continue;
    }
    if (num <= m) return false;
    else return true;
}
int main()
{
    while (~scanf("%d %d", &m, &n))
    {
        for (int i = 0; i < n; i++) {
            scanf("%d",&A[i]);
        }
        sort(A,A+n);
            double left = 0, right = 10000, mid, ans;
            while (right - left >= eps)
            {
                mid = (left + right) / 2.0;
                if (judge(mid))
                {
                    left = mid;
                }
                else{
                    right = mid;
                    ans = mid;
                }
            }
            printf("%.1lf
", ans);
    }
}

1052: [HAOI2007]覆盖问题(二维覆盖问题)

1052: [HAOI2007]覆盖问题

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1540  Solved: 705
[Submit][Status][Discuss]

Description

  某人在山上种了N棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄
膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个L*L的正方形塑料薄膜将小树遮起来。我们不妨将山建
立一个平面直角坐标系,设第i棵小树的坐标为(Xi,Yi),3个L*L的正方形的边要求平行与坐标轴,一个点如果在
正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求L最小值。

Input

  第一行有一个正整数N,表示有多少棵树。接下来有N行,第i+1行有2个整数Xi,Yi,表示第i棵树的坐标,保证
不会有2个树的坐标相同。

Output

  一行,输出最小的L值。

Sample Input

4
0 1
0 -1
1 0
-1 0

Sample Output

1

HINT

100%的数据,N<=20000

Source

这道题总体的思路还是二分答案+贪心验证 只不过这道题是从一维推广到二维了而已。

题意:网格图,给出nn个点,要求用3个边长相同的正方形覆盖所有点,求最小边长.

如何贪心验证呢?我们注意到是3个正方形.为什么是3个?

我们先找出覆盖所有点的最小距形,那么距形的四条边必须有正方形贴着,而又是3个正方形,所以至少要有1个正方形同时贴着两条边.

1.贴着的边相对:这样的话三个正方形都同时贴着相对的两条边,比如是上下两条边,那么贴着左边的那个正方形就贴着3条边,在距形的一角.

2.贴着的边相邻:这样的话这个正方形就在距形的一角.

所以我们递归的把正方形放在距形的一角,然后去掉已经覆盖了的点,继续放正方形即可.(贪心的思路)

原题解博客(https://www.cnblogs.com/Sunnie69/p/5649055.html)

洛谷 P1824 进击的奶牛 【二分答案】(求最大的最小值)

题目描述

Farmer John建造了一个有N(2<=N<=100,000)个隔间的牛棚,这些隔间分布在一条直线上,坐标是x1,...,xN (0<=xi<=1,000,000,000)。

他的C(2<=C<=N)头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?

输入格式:

第1行:两个用空格隔开的数字N和C。

第2~N+1行:每行一个整数,表示每个隔间的坐标。

输出格式:

输出只有一行,即相邻两头牛最大的最近距离。

输入样例#1:
5 3
1 
2 
8 
4 
9 
 
输出样例#1: 
3

解题思路:
像这种求最大最小值,最小最大值得问题都是典型的二分答案题,二分答案的主要难点在于juge()函数,此题下面给出了两个不同思路的juge函数。

要注意的是如何根据所枚举的答案来将隔间分隔,因为求的是最大的最近距离,这个距离要是每一次分隔距离中最短的。接下来分析,假设隔间的坐标没有规定在哪的话,那么什么时候最近距离最大呢?毫无疑问,是当所有的距离
相同的时候,最近距离最大。但是此题每个隔间的坐标有规定,使得不一定能使每一段的距离都能够相等,所以,此时求最近距离的最优思路就是:

   每一段区间距离都应该大于或等于m(但要尽可能的接近最近距离),这样才能使最近距离最大
 所以一旦所枚举的隔间距离恰好大于最近距离的时候,就在该隔间放牛,毫无疑问,这样得到的最近距离才会尽可能的大

原博客链接(https://www.cnblogs.com/00isok/p/9063340.html)

洛谷OJ - P1316 - 丢瓶盖(二分答案)

二分法,终点在于写check函数,第一个瓶盖是必选的,之后贪心的选择第一个能让距离大于等于所check的答案,然后再以这个瓶盖继续贪心选择下一个。之后判断选择的瓶盖数量。

#148. 【NOIP2015】跳石头

#include<stdio.h>
#include<iostream>
using namespace std;
int l,n,m;
int a[50005];
int L;
int check(int x)
{
    int last = 0;
    int ans = 0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]-last<x)
            ans++;
        else
            last = a[i];
    }
    if(ans>m)return 0;
    return 1;
}
int main()
{
    scanf("%d%d%d",&L,&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    a[n+1]=L;n++;
    int l = 0,r = L;
    while(l<=r)
    {
        int mid = (l+r)/2;
        if(check(mid))l=mid+1;
        else r=mid-1;
    }
    printf("%d
",l-1);
}

原博客链接:https://www.cnblogs.com/qscqesze/p/4955270.html

原文地址:https://www.cnblogs.com/visper/p/10174705.html