贪心法求解三种有关区间覆盖问题

                                               基于贪心算法的几类区间覆盖问题

(1)区间完全覆盖问题

问题描述:给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖

样例:

区间长度8,可选的覆盖线段[2,6],[1,4],[3,6],[3,7],[6,8],[2,4],[3,5]

解题过程:

1将每一个区间按照左端点递增顺序排列,拍完序后为[1,4],[2,4],[2,6],[3,5],[3,6],[3,7],[6,8]

2设置一个变量表示已经覆盖到的区域。再剩下的线段中找出所有左端点小于等于当前已经覆盖到的区域的右端点的线段中,右端点最大的线段在加入,直到已经覆盖全部的区域

3过程:

假设第一步加入[1,4],那么下一步能够选择的有[2,6],[3,5],[3,6],[3,7],由于7最大,所以下一步选择[3,7],最后一步只能选择[6,8],这个时候刚好达到了8退出,所选区间为3

4贪心证明:

需要最少的线段进行覆盖,那么选取的线段必然要尽量长,而已经覆盖到的区域之前的地方已经无所谓了,(可以理解成所有的可以覆盖的左端点都是已经覆盖到的地方),那么真正能够使得线段更成的是右端点,左端点没有太大的意义,所以选择右端点来覆盖

(2)最大不相交覆盖

问题描述: 给定一个长度为m的区间,再给出n条线段的起点和终点(开区间和闭区间处理的方法是不同,这里以开区间为例),问题是从中选取尽量多的线段,使得每个线段都是独立的,就是不和其它有任何线段有相交的地方
样例:

区间长度8,可选的覆盖线段[2,6],[1,4],[3,6],[3,7],[6,8],[2,4],[3,5]

解题过程:

对线段的右端点进行升序排序,每加入一个线段,然后选择后面若干个(也有可能是一个)右端点相同的线段,选择左端点最大的那一条,如果加入以后不会跟之前的线段产生公共部分,那么就加入,否则就继续判断后面的线段

1 排序: 将每一个区间按右端点进行递增顺序排列,拍完序后为[1,4],[2,4],[2,6],[3,5],[3,6],[3,7],[6,8]

2 第一步选取[2,4],发现后面只能加入[6,8],所以区间的个数为2
3 贪心证明: 因为需要尽量多的独立的线段,所以每个线段都尽可能的小,对于同一右端点,左端点越大,线段长度越小。那么为什么要对右端点进行排序呢?如果左端点进行排序,那么右端点是多少并不知道,那么每一条线段都不能对之前所有的线段进行一个总结,那么这就明显不满足贪心的最有字结构了。

(3)区间选点问题

问题描述:给定一个长度为m的区间,再给出n条线段和这n条线段需要满足的要求(要求是这n条线段上至少有的被选择的点的个数),问题是整个区间内最少选择几个点,使其满足每一条线段的要求.

样例:略

解题过程:将每个线段按照终点坐标进行递增排序,相同终点的前点坐标大的在前面,一个个将其满足

贪心证明:
要想使得剩下的线段上选择的点最少,那么就应该尽量使得已经选择了的点尽量能在后面的线段中发挥作用,而我们是从左往右选择线段的,那么要使得选取的点能满足后面线段的要求,那么必须是从线段的有端点开始选点,那么问题(2)一样涉及到一个问题,如果是按照线段的左端点对线段进行排序的话,不知道右端点的话,每一条线段都不能对之前已经操作过的所有线段进行一个总结,那么这就同样不满足贪心算法的最优子结构性质了。

可以解决的实际问题:数轴上面有n个闭区间[a,b],取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)


时间: 2024-08-01 12:39:33

贪心法求解三种有关区间覆盖问题的相关文章

用贪心法求解背包问题的解决方法_C 语言

贪心方法:总是对当前的问题作最好的选择,也就是局部寻优.最后得到整体最优.应用:1:该问题可以通过"局部寻优"逐步过渡到"整体最优",这是贪心选择性质与"动态规划"的主要差别.2:最优子结构性质:某个问题的整体最优解包含了"子"问题的最优解.完整的代码如下: 复制代码 代码如下: #include "iostream"using namespace std;struct goodinfo{ float p;

c++-贪心法 区间完全覆盖问题

问题描述 贪心法 区间完全覆盖问题 50C 给定一个长度为m的区间~再给出n条用闭区间表示的线段~用贪心法求出最少的线段能覆盖完m区间~例: 区间长度8,可选的覆盖线段[26][14][36][37][68][24][35] 现需要代码 c++的 过程 : 1将每一个区间按照左端点递增顺序排列,拍完序后为[14],[24],[26],[35],[36],[37],[68] 2设置一个变量表示已经覆盖到的区域.再剩下的线段中找出所有左端点小于等于当前已经覆盖到的区域的右端点的线段中,右端点最大的线

回溯法——求解0-1背包问题

         以前研究过一个简单的N皇后问题,对回溯法也有了个模糊的认识,大致理解就是:先一直做某件事,当完成某个条件时或者是触犯某个条件时,再返回到最近的一个类似还原点的地方.        在用回溯法求解0-1背包问题的时候,主要遇到三个相对难解决的问题:1,什么是界限函数:2,什么时候用它:3,回溯到哪儿.    什么是界限函数?         如下图:             当我们身在一棵搜索空间树中,站在一个K点举棋不定的时候,我们可以用它估算如果我们继续向下走,我们走完本段路

【OJ】贪心法(最小字典序)poj3617 Best Cow Line// acmclub 12701/12695

     题目链接:      点击打开链接 /* POJ 3617 Best Cow Line 贪心法--最小字典序 */ #include<stdio.h> #include<string.h> char ss[30010]; int main(){ int n,left1;scanf("%d",&n); getchar();//不可少,接收前一个\n for(int j=0;j<n;j++){// // scanf("%c"

贪心法 最小圈基问题-贪心法解决最小圈基问题。

问题描述 贪心法解决最小圈基问题. 在网上找不到关于最小圈基的资料,不知道有木有大神来拯救下我这个小白新手- 解决方案 我的算法实验有这个,自己写了,不是很好,可以参考我的博客

贪心法 背包问题 一道简单的实际问题 不知道大难如何计算出来的。

问题描述 贪心法 背包问题 一道简单的实际问题 不知道大难如何计算出来的. 问题:设有背包问题实例n=7,M=15(背包载重),(w0,w1,...,w6)=(2,3,5,7,1,4,1), 物品装入背包的收益为:(p0,p1,p2,p3,p4,p5,p6)=(10,5,15,7,6,18,3). 求这一实例的最优解和最大收益 答案:最优解:(p0/wo,p1/w1,p2/w2,p3/w3,p4/w4,p5/w5,p6/w6)=(10/2,5/3,15/5,7/7,6/1,18/4,3/1)(x

struct-关于使用回溯法求解迷宫问题

问题描述 关于使用回溯法求解迷宫问题 #include using namespace std ; const int m = 4 , p = 4 ; struct offsets { int a , b ; char *dir ; }; offsets move[8] ; int Maze[m+2][p+2] ; int mark[m+2][p+2] ; int main (){ int i , j; int SeekPath (int x ,int y ) ; offsets move[8]

【OJ】贪心法 (区间问题——木棒)1129/

题目链接:点击打开链接 /* 贪心法 (区间问题--木棒)1129/ */ #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int maxn=5010; typedef pair<int,int> P; pair<int,int>itv[maxn]; int ok[maxn]; bool comp( P a,const P &

贪心法——活动选择问题和背包问题

        今天上午听了米老师讲的算法,感觉收获很多,对于算法更加有信心了.首先,先来宏观看一下:                      这三种算法总的来说,刚开始看的时候不知道怎么下手,但是看多了也会有那么一点儿感觉.分治法是这三种算法里面都有的思想,动态规划和贪心都是将问题分解成子问题求解,但动态规划里面的子问题都带有联系,而贪心算法里面的子问题都相对独立,唯一不同的是,贪心算法要首先想出一个解决方案来构造求解最优解的过程.      宏观介绍下算法后,来看看贪心算法的两个实例.