zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    HashMap 统计一个字符串中每个单词出现的次数
    iOS .a静态库的制作及使用
    iOS framework静态库中使用xib和图片资源详解
    iOS 工程套子工程,主工程和framework工程或.a library静态库工程联调
    iOS 最新framework和.a静态库制作及使用全解(含工程套工程,多工程联调)
    iOS9新特性 3DTouch 开发教程全解(含源码)
    iOS GCD NSOperation NSThread等多线程各种举例详解
    Mac Beyond Compare 永久试用
    cocoapods 常见问题
    iOS 常用工具库LFKit功能介绍
  • 原文地址:https://www.cnblogs.com/visper/p/10174705.html
Copyright © 2011-2022 走看看