线段区间的覆盖

用i表示x轴上坐标为[i-1,i]的区间(区间长度为1),并给出M个不同的整数来表示M个这样的区间。现在要求画出几条线段覆盖住所有的区间,条件是:每条线段可任意长,但要求所画线段长度之和最小,并且线段的数目不超过N。

举例:给出M=6,1,2,4,5,7,11,分别表示6个长度为1的区间,要求用不超过N=3条线段将其覆盖。

上图给出了一种可行的覆盖方案,用三段长线段覆盖住6个长度为1的小线段,使得3短线段长度之和最小。

l  算法思想

运用贪心算法,M个线段会产生M-1个间断,间断有大有小,按照从大到小的顺序把线段间的间隔排好。假设初始状态下有一整条线段覆盖整个区域,每一步都从间隔最大的位置上断开该线段,直至断开N-1次,此时一整条线段就被分成了N截且这N截线段的长度和最小。

l  程序模型的建立与设计流程

如果N>=M,显然用M条长度为1的线段就可覆盖所有区间,所求的线段总长度也就为M。如果N,要另想办法。

①  N=1,那么所需线段总长为position[M-1]-position[0]+1;

②  N=2,那么相当于把①中的长线段分成两截。找到最大距离distance[i]=position[i]-position[i-1]-1 (1

③  N=3,同理,将distance第二大的位置断开,于是便形成3截线段,并且长度和最小。

④  N=k(k>1)时,只要在N=k-1时最小总长的覆盖方案下,找到被同一条线段覆盖最大的两个区间,“贪心”地从间隔处断开并适当调整两条线段的端点,就可以得到总长最小的方案。

l  数据结构的选用

可用整型数组position[M]表示所有的区间,并假设position[M]已按从小到达的顺序排好了。

l  源程序编码清单

#include

using namespace std;

const int SIZE=200;

void Sort(int value[],int nNumber)              //对nNumber个值从大到小排列

{

for(int i=0;i

for(int j=0;j

if(value[j]

{

int temp=value[j];

value[j]=value[j+1];

value[j+1]=temp;

}

}

void main()

{

int M=0;

int position[SIZE];

cout<<"请输入待覆盖的区间总数M="<<endl;

cin>>M;

int i=0;

cout<<"请具体地输入第"<<M

<<"个要覆盖的区间:"<<endl;

for(i=0;i

{

cin>>position[i];

}

Sort(position,M);

int distance[SIZE-1];

for(i=0;i

distance[i]=position[i]-position[i+1]-1;

Sort(distance,M-1);

int N=1;                                     //可用于覆盖的线段总数

cout<<"请输入可用于覆盖的线段总数N="<<endl;

cin>>N;

//**********贪心算法*************************

if(N>=M)

{

cout<<"最小的线段总长为"

<<M<<endl;

return;

}

else if(N

{

int nLine=1;                           //记录当前线段总数

int nTotalLength=position[0]-position[M-1]+1;//记录当前情况下所用线段的总长

int nDivide=0;                         //记录当前最大的未断开的区间位置

while((nLine0]))

{

nLine++;

nTotalLength-=distance[nDivide];

nDivide++;

}

cout<<"最小的线段总长为"

<<nTotalLength<<endl;

}

}

l  程序输入、输出

l  时间与空间复杂度分析

算法时间复杂度为O(nlogn)+O(n)。

l  程序使用说明

①  对position的排序无论从大到小还是从小到大没有区别,不影响区间距离的计算。

②  注意while循环的两个条件

l  总结与完善

这个程序可以得到最小总长条件下所需的最少线段的数目,但并不能给出这些线段的端点信息。可以进一步对程序修改以添加此功能。

时间: 2024-10-20 00:50:57

线段区间的覆盖的相关文章

每次输出有几条线段能完全覆盖大于自己和hdu5372相反 树状数组或线段树 poj 2481 Cows

http://poj.org/problem?id=2481 Cows Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 14762   Accepted: 4886 Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one

nyoj 12 喷水装置(二)【贪心】+【区间完全覆盖覆盖】

题意:... 这道题就是区间问题三种中的区间完全覆盖问题,不懂的可以看我上一篇也是区间完全覆盖. 直接上代码: #include <stdio.h> #include <math.h> #include <algorithm> using std::sort; struct node{ double le, ri; }s[1005]; int cmp(node a, node b) { return a.le < b.le; } int main() { int

当前插入的线段能完整覆盖存在的几条线段 树状数组 HDU 5372 Segment Game

http://acm.hdu.edu.cn/showproblem.php? pid=5372 Segment Game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1284    Accepted Submission(s): 375 Problem Description Lillian is a clever girl so

HDU 4106 Fruit Ninja 区间k覆盖问题 最小费用流

题目链接:点击打开链接 题意: 给定n长的序列,m ,k 选择一些数使得 选择的数和最大.输出和. 限制:对于任意的区间[i, i+m]中至多有k个数被选. 思路: 白书P367,区间k覆盖问题,把一个区间看成一个点,那么选了一个点就相当于覆盖了m个区间. #include<iostream> #include<stdio.h> #include<string.h> #include<queue> #include<math.h> using n

poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙

/** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi),以及权值wi.选出一些区间,满足权值和最大且任何一个点不会被超过k个区间覆盖. 思路: 建图:对于每个区间(ai,bi). ai->bi,cap = 1,cost = -wi; (离散化后的ai,bi) 所有区间的端点放到数组,进行从小到大排序,去重,离散化,在数组内相邻的u端点,v端点.u->

hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙

/** 题目:hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4106 题意:给你n个数,每连续m个数,最多选k个数,问可以选的数的权值和最大多少. 思路:可以转化为区间k覆盖问题.区间k覆盖问题是每个点最多被k个区间覆盖.本题是每个区间最多选k个点. 刚好相反.我的做法有点不同其他博客那种做法.当然本质一样. 我这里的i就是原来n个数的下标,现在作为图中该数的节点编号

ACM-ICPC 2018 焦作赛区网络预赛 F. Modular Production Line (区间K覆盖-最小费用流)

很明显的区间K覆盖模型,用费用流求解.只是这题N可达1e5,需要将点离散化. 建模方式步骤: 1.对权值为w的区间[u,v],加边id(u)->id(v+1),容量为1,费用为-w; 2.对所有相邻的点加边id(i)->id(i+1),容量为正无穷,费用为0; 3.建立源点汇点,由源点s向最左侧的点加边,容量为K,费用为0,由最右侧的点向汇点加边,容量为K,费用为0 4.跑出最大流后,最小费用取绝对值就是能获得的最大权 #include<bits/stdc++.h> using n

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

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

Count the Colors (zoj 1610 线段树 区间颜色覆盖)

Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can s