贪心算法-----区间覆盖问题

(一)点覆盖区间(雷达/灌溉喷头)

题目描述:假设海岸线是一条无限延伸的直线。陆地在海岸线的一侧,而海洋在另一侧。每一个小的岛屿是海洋上的一个点。雷达坐落于海岸线上,只能覆盖d距离,所以如果小岛能够被覆盖到的话,它们之间的距离最多为d。题目要求计算出能够覆盖给出的所有岛屿的最少雷达数目。对于每个小岛,我们可以计算出一个雷达所在位置的区间。

       

算法实现:

//2018年6月11日与辽宁沈阳东北大学

#include 
#include 
#include 
using namespace std;

struct Qujian
{
	double start, end;

};

int radarNum = 1;


//这个函数写法值得学习

/************************************************************/
int cmp(const void *a, const void *b)
{
	return (*(Qujian *)a).start>(*(Qujian *)b).start ? 1 : -1;
}
/**********************************************************/
int main(void)
{
	double x, y;
	cout << "请输入岛屿数目和雷达最大探测距离  ";
	int num_island; double DisMax;

	cin >> num_island >> DisMax;
	Qujian qujian[50];

	for (int i = 0; i < num_island; ++i)
	{
		cout << "请输入第"<> x >> y;

		if (y > DisMax)
		{
			cout << " 这个岛屿检测不到" << endl;
			exit(-1);
		}

		qujian[i].start = x - sqrt(DisMax*DisMax -y*y);
		qujian[i].end = x +sqrt(DisMax*DisMax - y*y);
	}

	qsort(qujian, num_island, sizeof(qujian[0]), cmp);

	for (int j = 1; j <= num_island; ++j)
	{
		if (qujian[j].start >= qujian[0].start&&qujian[j].end <= qujian[0].end)
		{
			qujian[0].end = qujian[j].end;
		}

		if (qujian[j].start > qujian[0].end)
		{
			//qujian[0].start = qujian[j].start;

			qujian[0].end = qujian[j].end;
			radarNum++;
		}
	}

	cout << "需要雷达总数是:" << radarNum << endl;

	return 0;

}

 

问题转化为如何用尽可能少的点覆盖这些区间。先将所有区间按照左端点大小排序,初始时需要一个点。如果两个区间相交而不重合,我们什么都不需要做;如果一个区间完全包含于另外一个区间,我们需要更新区间的右端点;如果两个区间不相交,我们需要增加点并更新右端点。

 

 

草图:

贪心算法-----区间覆盖问题_第1张图片

贪心算法-----区间覆盖问题_第2张图片

 

 

 

 

(二)线段覆盖区间

 

//2018年6月11日于辽宁沈阳
//Author:Mr Yang

//(二)线段覆盖区间
//
//题目描述:
//
//用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
//算法思想:
//第一步将所有区间间距排序,再连接间距最短的两个线段(间距大小并列的只连接一个),统计这时候有多少条线段,如果大于限制线段树就继续连接区间间距次小的两个区间......直到线段数目等于规定最大线段数为止

//算法实现:

#include 
#include 
#include 

#define N 200

using namespace std;

struct Qujian
{
    int start, end;
};

Qujian qujian[200];     //存放输入区间

//int cmp(const int&a, const int&b)
//{
    //return (*(Qujian *)a).start>(*(Qujian *)b).start ? 1 : -1;
//    return a
//}
int main()
{
    int PointNum, segmentLimit;
    cout << "请输入区间数目和线段限制最大数:" << endl;
    cin >> PointNum >> segmentLimit;

    cout << "请输入具体区间: " << endl;
    int buf_Point;
    for (int j = 0; j > buf_Point;

        qujian[j].start = buf_Point - 1;
        qujian[j].end = buf_Point;
        
    }

    int Distance[N] = {-1};   //Distance[N]存相邻区间的距离
    for (int j = 0; j < PointNum-1; j++)
    {
        Distance[j] = qujian[j + 1].start - qujian[j].end;

    }

    //qsort(Distance, PointNum - 1, sizeof(Distance[0]), cmp);
    sort(Distance, Distance + PointNum - 1);
    //cout << Distance[0] << Distance[1] << Distance[2] << Distance[3]<< endl;看看排序拍的对不

    int ResLength = 0; int SegmentNum = PointNum;
    for (int j = 0; j < PointNum - 1; ++j)
    {
        if (Distance[j] > 0&&j==0)
        {
            ResLength = Distance[j] + 2;
            SegmentNum--;

            if (SegmentNum == segmentLimit)
            {
                ResLength += (PointNum - j - 2);//ResLength=ResLength+(PointNum-1-(j+1)
                break;
            }
        }
        else if (Distance[j] > 0 && j > 0)
        {
            ResLength = ResLength+ Distance[j] + 1;
            SegmentNum--;

            if (SegmentNum == segmentLimit)
            {
                ResLength+=(PointNum - j - 2);
                break;
            }
        }
    }

    cout << ResLength << endl;
    return 0;

}

 

 

贪心算法-----区间覆盖问题_第3张图片

 

 

参考:https://blog.csdn.net/cordova/article/details/50853147

转载必须注明出处

你可能感兴趣的:(算法篇,贪心)