您的位置:首页 > 编程语言 > C语言/C++

C++实现 贪心算法-区间覆盖问题

2016-03-11 09:18 162 查看
题目描述:
用i来表示x坐标轴上坐标为[i-1,i]的长度为1的区间,并给出n(1≤M≤200)个不同的整数,表示n个这样的区间。
现在要求画m条线段覆盖住所有的区间,
条件是:每条线段可以任意长,但是要求所画线段的长度之和最小,并且线段的数目不超过N(1≤N≤50)。
输入:
输入包括多组数据,每组数据的第一行表示点数n和所需线段数m,后面的n行表示点的坐标
输出:
输出每组按规定线段条数被覆盖的线段的最短总长度。
示例输入:
5 3
1 3 5 8 11
示例输出:

7
分析:
方法一:(传统的一般解法)
先用一条最长的线段把整个区间覆盖起来,然后把区间点之间的空隔线段按照先长后短的顺序一一去掉,也就是贪心地使总线段长度尽可能短,直到线段的数量增加到到规定的数目停止;


贪心算法-区间覆盖问题" TITLE="C++实现 贪心算法-区间覆盖问题" />


方法二:(个人原创想到的思路)
其实思想与方法一一样,只不过这里逆向思考不是先用一条最长的线段把整个区间覆盖,而是用最短的线段把所有的区间点覆盖,也就是每个区间点用一条单位长度的线段覆盖,那么有n个区间点,就需要总长度为n的线段,然后把每个小线段一一连接起来,还是贪心地线连接距离最短的,尽量使总长度最短,直到线段数量减少到规定数目停止。


贪心算法-区间覆盖问题" TITLE="C++实现 贪心算法-区间覆盖问题" />


C++程序实现:
#include iostream
#include algorithm
using namespace std;
//方法一
//降序排列函数指定,sort库函数默认是升序的
int descend(int a,int b)
{
return a>b;
}
int main()
{
int n,m,minLength;//区间点的个数n和所需的线段数m,覆盖线段的最短总长度minLength
int point[200],distance[200];//区间点数组point与区间点之间的距离数组distance
while(cin>>n>>m)//用户输入区间点的个数n和所需的线段数m
{
for(int i=0;i
{
cin>>point[i];
}
sort(point,point+n);//升序排列
minLength=point[n-1]-point[0]+1;//全部覆盖的最长的一条线段的长度
for(i=0;i
distance[i]=point[i+1]-point[i]-1;//将每两个区间点之间的距离存入distance数组
int nn=n-1;//距离数组的实际长度
sort(distance,distance+nn,descend);//将区间距离数组降序排列
for(i=0;i
minLength-=distance[i];//将链接区间点之间的线段按先去长后去短的顺序一一去掉知道线段条数达到要求
cout<<minLength<<endl;
}
return 0;
}
//方法二
int main()
{
int n,m,minLength;//区间点的个数n和所需的线段数m,覆盖线段的最短总长度minLength
int point[200],distance[199];//区间点数组point与区间点之间的距离数组distance
while(cin>>n>>m)//用户输入区间点的个数n和所需的线段数m
{
for(int i=0;i
{
cin>>point[i];
}
sort(point,point+n);//升序排列
minLength=n;//每个区间点用一个单位的线段覆盖时的线段的总长度
for(i=0;i
distance[i]=point[i+1]-point[i]-1;//将每两个区间点之间的距离存入distance数组
int nn=n-1;//距离数组的实际长度
sort(distance,distance+nn);//将区间距离数组升序排列
for(i=0;i
minLength+=distance[i];//将每一段单位线段按照距离最近一一连接起来,直到线段数目达到要求
cout<<minLength<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: