ACM知识点 之 贪心(2)选择不相交区间

转载地址:http://blog.csdn.net/liuxucoder

之前基本了解了贪心的基本思想,现在我们来看一下比较经典的几个贪心问题。

这篇文章讨论的是”选择不相交区间“,具体什么意思,我们同样先看一道题。



题目来源:NYOJ 14

                            会场安排问题
                时间限制:3000 ms  |  内存限制:65535 KB
                            难度:4(这个难度真的很唬人~~)

描述

学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办。小刘的工作就是安排学校小礼堂的活动,每个时间最多安排一个活动。现在小刘有一些活动计划的时间表,他想尽可能的安排更多的活动,请问他该如何安排。

输入

第一行是一个整型数m(m<100)表示共有m组测试数据。

每组测试数据的第一行是一个整数n(n<1000)表示该测试数据共有n个活动。

随后的n行,每行有两个正整数Bi,Ei(0<=Bi,Ei<10000),分别表示第i个活动的起始与结束时间(Bi<=Ei)

输出

对于每一组输入,输出最多能够安排的活动数量。

每组的输出占一行

样例输入

2

2

1 10

10 11

3

1 10

10 11

11 20

样例输出

1

2

提示

注意:如果上一个活动在t时间结束,下一个活动最早应该在t+1时间开始



首先,把题目中的信息转换为模型。

给你n个区间,求得不相交区间的数目。(P.S.也就是一句话的事~~题目太经典,无需多言)

下面我们来分析这道题是否能用贪心的方法来做,让我们回顾贪心的三个关键点

1.问题可以分解为多个子问题。

那么当前问题可不可以? 当然可以,选择不相交区间的过程,完全可以分解为:给定一个区间,按照某种规则对接下来的多个区间进行比较,然后得出最优结果的过程。

这里的规则指的是:对于当前区间来说,优先选择离当前区间距离最近而且区间最短的下一个区间。

2.总问题的最优解可由各个子问题的最优解得到。

这个也很好理解,由于每个子问题求得的永远是离当前区间距离最近而且区间最短的下一个区间,而下一个区间也是按照这个规则来寻找另外一个区间的。所以对于最优解集合的解释就是“对于每一个区间来说,后面的那个区间就是离它最近(空白少)而且区间最短(占用少)的”,这也就是说,满足总体问题最优解的“尽可能多的选择区间”

3.子问题具有”无后效性“,当前子问题的求解不会影响到之前子问题的解。

这个题目乍一看貌似是不满足无后效性的,因为给定的数据顺序混乱,似乎每一次寻找都要进行一次遍历,但是这个过程可以通过排序的方式解决。这种处理原始数据,使得处理过程更加简单快捷的方法,叫做预处理。

综上,这道题(或者说这类问题)确实是可以通过贪心策略来取得最终的解得。

那么,预处理过程应该怎么排序呢?

我们再来聊一聊最优解的判定规则,也就是两点:

1.区间最短(长度)

2.间隔最小(两端位置)

那么我们是按照哪一种指标来进行排序呢?答案很明显,长度肯定是不靠谱的。因为单单通过长度进行排序,我们并不能对两端位置进行控制,并没有减少我们对于数据的判定过程,反而可能会加大难度。

那么我们按照两端位置进行排序,排序的规则很明显,按照从小到大的顺序进行排序。

网络上很多人采用以后端点排序的方式,可能会让刚接触的人误以为只能通过后断电排序,其实不然,采用哪个端点排序都是可以的。而不管选择哪一个来排序,其原理和本质都一样,都是为了方便操作,将其有序化。

那么我们的贪心策略可以用伪代码描述为:

while(剩余区间的数目不为0)
{
    if(找到符合条件的下一个区间)
    {
        当前区间 = 下一个区间;
        答案数+1;
    }

    区间数--;
}

话说至此,这道题目我们就可以开始做了。

下面附上AC代码:

/*
************************************
    Title: NYOJ41--会场安排问题
************************************
    Date:2015/07/120
************************************
    author:刘旭
************************************
Memory:308KB
Time:80ms
************************************
*/

#include<stdio.h>
#include<algorithm>

using namespace std;

#define MAX 10050
struct Node
{
    int x,y;
} map[10005];  /*定义结构体数组*/

int cmp(Node a,Node b)
{
    if(a.y!=b.y)
    {
        return a.y<b.y;
    }

    return a.x<b.x;
}

int main()
{
    int m = 0;
    scanf("%d",&m);
    while(m--)
    {
        int  num = 0;
        scanf("%d",&num);
        for(int i = 0; i < num; i++)
        {
            scanf("%d%d",&map[i].x,&map[i].y);
        }

        sort(map,map+num,cmp);

        int start = map[0].y;   ///起始位置
        int count=1;    ///答案数
        int num_last = num;///剩余区间数目

        while(num_last > 0)
        {
            if(map[num - num_last].x > start)
            {
                count++;
                start = map[num - num_last].y;
            }

            num_last--;
        }

        printf("%d\n",count);
    }
    return 0;
}

行文至此,整个问题便已解决。说句实话,多写写分析什么的,确实挺爽的~

时间: 2024-10-11 11:07:55

ACM知识点 之 贪心(2)选择不相交区间的相关文章

贪心算法选择不相交区间

Input 输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示.n=0表示输入结束,不做处理. Output 对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行. Sample Input 12 1 3 3 4 0 7 3 8 15 19 15 20 10 15 8

ACM知识点 之 贪心(1)理论初探

转载地址:http://blog.csdn.net/liuxucoder 目录(?)[+] 等待了一年时间,这个系列的坑终于又开始填了-- 不说废话,直接开始正题. 1.何为贪心? 贪心算法实际上指的是把问题划分成一个一个的子问题,然后针对当前的子问题,求出局部最优解,然后将子问题的最优解合并,最终获得总问题的最优解. 值得注意的是,在对问题求解时,贪心算法总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,它做出的仅是在某种意义上的局部最优解. P.S:贪心子问题是独立的,有区别

最大不相交区间数+最少区间数覆盖问题 贪心思想

最大不相交区间数的一道题是hdu2037 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2037 题目给出n个区间,问最多有多少个区间没有重叠,只需要对区间右端点进行排序就行,因为一个节目结束得早的话就会为其他节目留下更多的时间,如果选择对节目的开始时间进行排序的话就会导致有一个节目迟迟不结束使得其他节目又没法开始的现象.右端点最小的第一个区间时一定要选的.这个可以简单地将其他右端值更大的区间跟他交换,就会发现不会产生更多的区间数,只会小于等于我们

HDU 4343 多查询求区间内的最大不相交区间个数-思维&amp;贪心-卡时间&amp;二分&amp;剪枝

题意:给你一些区间,现在有m个查询,求出每个查询的区间内的最大的不相交区间个数 分析: 几天前那道说谎问题时用dp的摞箱子模型求的最大的不相交区间个数,但是这题不能用这个方法,因为这题是动态的查询,不可能每个查询dp一次,超时. 这题用贪心策略.求区间[l~r]里的最大不相交区间,贪心策略就应该先选该区间内右端点最小的,这样给以后待选的区间留下更大的空间,所以我们的做法就是先按照区间的右端点排序,然后每次查询依次挑出查询区间里右端点最小的,并且把查询区间的左端点更新为刚才挑出的区间的右端点(这个

NYOJ_14会场安排问题(不相交区间)

会场安排问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办.小刘的工作就是安排学校小礼堂的活动,每个时间最多安排一个活动.现在小刘有一些活动计划的时间表,他想尽可能的安排更多的活动,请问他该如何安排. 输入 第一行是一个整型数m(m<100)表示共有m组测试数据. 每组测试数据的第一行是一个整数n(1<n<10000)表示该测试数据共有n个活动. 随后的n行,每

ACM知识点分类

ACM知识点分类  (红:完全没听说过 黄:听说过 绿:接触过做过题 蓝:很熟悉刷过专题 紫:见一道秒一道) 第一类:基础算法 (1)     基础算法:枚举,贪心,递归,分治,递推,构造,模拟 (2)     动态规划:背包问题,树形dp,状态压缩dp,单调性优化,插头dp (3)     搜索:dfs,bfs,记忆化搜索,优化与剪枝,双广,A*,IDA*,跳舞链 第二类:数据结构 (1)     简单数据结构:链表,栈和队列,串,树和二叉树,图,排序与检索 (2)     树形结构:线段树,

【置顶】ACM知识点分类

ACM知识点分类  (红:完全没听说过 黄:听说过 绿:接触过做过题 蓝:很熟悉刷过专题 紫:见一道秒一道) 第一类:基础算法 (1)     基础算法:枚举,贪心,递归,分治,递推,构造,模拟 (2)     动态规划:背包问题,树形dp,状态压缩dp,单调性优化,插头dp (3)     搜索:dfs,bfs,记忆化搜索,优化与剪枝,双广,A*,IDA*,跳舞链 第二类:数据结构 (1)     简单数据结构:链表,栈和队列,串,树和二叉树,图,排序与检索 (2)     树形结构:线段树,

最大不相交区间数

# 题意N个闭区间[ai,bi],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点).输出可选取区间的最大数量. # 题解1.将每个区间按照右端点从小到大排序2.从前往后依次枚举每个区间如果当前区间已经包含点pass否则选择当前区间的右端点因为是右端点从小到大易知正确 1 #include <bits/stdc++.h> 2 #define PII pair<int,int> 3 using namespace std; 4 const int N=1e5+10; 5

贪心算法设计 关于区间选择问题

/* 现在有n项工作,知道每一项工作的开始时间和结束时间,问最多可以选择多少工作 算法设计:贪心算法,不断选择不冲突的那些结束时间最短的工作 */ #include<iostream> #include<vector> #define max_n 100001 using namespace std; int N; //first is the start of the job,and the secone is the end time of the job typedef pa