C - 区间覆盖(贪心算法)

区间覆盖

  • 题意:
    数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
    覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。不可能办到输出-1

  • 输入输出:
    输入
    第一行:N和T
    第二行至N+1行: 每一行一个闭区间。
    输出
    选择的区间的数目,不可能办到输出-1
    在这里插入图片描述

  • 解题思路
    结构体node存储区间两个端点x和y,按照较小的端点x升序排列。首先区间覆盖需要满足从1开始,故先对第一个区间进行判断,若x值大于1则不满足条件,直接输出-1。

    定义变量len记录已经遍历过并被选中的区间端点的最大值,初始状态计数器count值为1,len值为第一个区间的y值,从第二个区间开始遍历,每次循环首先判断是否已经满足覆盖条件,若满足直接跳出循环,输出count。若不满足,判断下一个区间是否满足x值小于等于len+1同时y值大于len,若满足则记录该区间的y值maxlen,再从该区间向后遍历,如果还有其他满足条件且y值大于maxlen的,更新len值,若没有则直接更新len值,每更新一次计数器count加一。

    注意:不能直接更新len的原因
    例:
    3 10
    1 5
    4 8
    6 10
    若直接更新会导致区间(4,8)被选中,最终输出结果为3,显然结果错误。故应在(4,8)被选中时继续向后遍历查找有没有更优区间,即(6,10),若存在则直接更新len的值为10,否则会导致多选中不必要的区间,结果出错。

  • 代码实现

#include <iostream>
#include <cstdio> 
#include <algorithm>
using namespace std;

struct node
{
	int x,y;
}a[30000];

bool cmp(node a,node b)
{
	if(a.x!=b.x)
		return a.x<b.x;
	else
		return a.y>b.y; 
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int m,n;
	cin>>m>>n;
	int c,d;
	for(int i=1;i<=m;i++)
	{
		cin>>c>>d;
		a[i].x=c;
		a[i].y=d;
	}	
	sort(a+1,a+m+1,cmp);
	if(a[1].x>1)
	{
		cout<<-1<<endl;
	}
	else
	{
		int count=1;
		int len=a[1].y;
		for(int i=2;i<=m;i++)
		{
			if(len>=n)
			{
				break;
			}
			if(a[i].x<=len+1&&a[i].y>len)
			{
				int maxlen=a[i].y;
				for(int j=i;j<=m;j++)
				{
					if(a[j].x<=len+1)
					{
						if(a[j].y>maxlen)
						{
							maxlen=a[j].y;
							i=j;
						} 
					}
					else
						break;
				}
				len=maxlen;
				count++;
			}
		}
		if(len<n)
			cout<<-1<<endl;
		else
			cout<<count<<endl; 	
	}
}

发布了19 篇原创文章 · 获赞 0 · 访问量 654

猜你喜欢

转载自blog.csdn.net/Hdjjdsbjj/article/details/104732327