poj 2376 Cleaning Shifts( 贪心 )

 

题意:给出区间[ 1,T ]和N个小区间,要求用尽可能少的小区间覆盖区间[ 1,T ],输出最少的小区间数量;若不能覆盖,输出-1。

思路:贪心。

具体:令begin为当前未被覆盖的区间起点。

            贪心策略:选取包含点begin的区间中右端点最大的那个;若不存在包含begin的区间,输出-1。

证明:因为begin为未被覆盖的区间起点,所以begin一定要被小区间覆盖,将最优解中覆盖begin的小区间命名为区间X。

            以下使用剪贴技术证明。

            若存在包含begin的小区间Y( Y != X )使最终所需的小区间数少于原最优解,那么Y一定包含了X之后的某些小区间,

            即Y的右端点大于X的右端点,与贪心策略矛盾,得证。

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

const int Max = 25000;

// 对象
int N, T;
struct Interval {
	int b, e;
}I[Max];

// 函数
bool greater( const Interval & i1, const Interval & i2 )
{
	return i1.b < i2.b;
}

int Greedy()
{
	int num = 0; // 最少区间数 
	int	right = 0; // 已覆盖区间右端点
	int top = 0; // 集合首

	while( right < T ) {
		// 选出包含begin的区间中右端点最大的那个
		int begin = right + 1; // 待覆盖的起点
		for( int i = top; i < N; ++ i ) {
			if( I[i].b <= begin && I[i].e >= begin )
				right = I[i].e > right ? I[i].e : right;
			else if( I[i].b > begin ) {
				top = i;
				break;
			}
		}
		// 没有包含begin的区间
		if( begin > right ) break;
		else ++ num;
	}

	if( right == T ) return num;
	else return -1;
}

int main()
{
	scanf( "%d%d", & N, & T );
	for( int i = 0; i < N; ++ i )
		scanf( "%d%d", & I[i].b, & I[i].e );
	
	sort( I, I + N, greater );
	printf( "%d\n", Greedy() );
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值