POJ 2376 Cleaning Shifts

题目:

给定一个时间T和N个时间区间,求最少需要多少个区间覆盖总区间[1,T],无法覆盖区域[1,T]时输出-1。

例如T=10,有3个区间[1,7],[3,6],[8,10],则最少需要两个区间来覆盖,选择区间1和区间3。

解题思路:

使用贪心法。首先将区间按开始时间从小到大排序,开始时间相等按结束时间从小到大排序。

1 如果第一个区间不是从1开始,则无法覆盖,输出-1。

2 令当前覆盖到的时间time为开始时间为1的区间中结束时间的最大值。

3 从开始时间不为1的区间开始循环遍历。

4 选择合法区间中结束时间值最大的那个区间,合并到[1,time],合并后time为选择的区间的结束时间。所谓合法区间是指区间的起始时间start<=time+1,这样才能和区间[1,time]合并。如果没有找到合法区间或者找到的区间结束时间比time小,则无法覆盖,结束循环。

5 循环结束后,根据time是否大于等于T,输出结果。

代码:

#include<stdio.h>

typedef struct
{
	int start, end;
} interval;

interval data[25000];

int cmp(const void *a, const void *b)//按start从小到大,end从小到大排序 
{
	interval *p1, *p2;
	p1=(interval*)a;
	p2=(interval*)b;
	if(p1->start != p2->start) return p1->start - p2->start;
	else return p1->end - p2->end;
}

int main()
{
	int n,t,i,j,ans,time,max_end;
	scanf("%d %d", &n, &t);
	for(i=0; i<n; i++) scanf("%d %d", &data[i].start, &data[i].end);
	
	//排序
	qsort(data, n, sizeof(interval), cmp);
	
	//区间覆盖 
	if(data[0].start != 1) {printf("%d\n", -1); return 0;} //不是从1开始,无法覆盖 
	else
	{
		time=data[0].end;
		i=1;//i指向下一个区间 
		while(data[i].start == 1) {time=data[i].end; i++;}
	}

	ans=1;
	while(time<t)
	{
		//使用贪心原则查找下一个区间,取合法区间中结束时间最大的那个 
		if(i>=n) break;
		j=i;
		max_end=data[i].end;
		i++;
		while(i<n && data[i].start <= time+1)
		{
			if(data[i].end > max_end) {j=i; max_end=data[i].end;}
			i++;
	  }
		if(max_end <= time || data[j].start>time+1) break; //结束时间没有增长或选择的区间为非法区间,无法覆盖 
		else
		{ //增加一个区间,当前时间变为选择的区间的结束时间 
			ans++;
			time=data[j].end;
		}
	}
	
	if(time<t) printf("%d\n", -1);
	else printf("%d\n", ans);
	
	return 0;
} 


你可能感兴趣的:(struct,p2p)