HDU 3650 Hot Expo(气球染色 , 贪心 )

题目链接 :HDU 3650 Hot Expo


【题目大意】


Sunny在逛上海世博会,世博会有很多国家的场,每个场子每天同一时段都有一场精彩的表演。表演开始时间 为beg,结束时间为 end ,Sunny有强迫症,他想要看完所有给定表演,并且一秒钟 都不拉下,也就是说 ,表演一 beg =1 end =4 表演二 beg = 4 ,end =5.那么为了完整的看表演二,Sunny需要在第二天再来看 表演二。

现在给出所有表演的 beg end,让你求出Sunny看完所有表演所花的全部天数。


这个题和气球染色的如出一辙。

给定区间,将区间的气球染色一次。问最后区间内的哪个气球染色次数最多,输出最大的染色次数。

用paint【1~n】 表示每个气球的染色次数,初始化为0;

很容易想到,每次染色,将区间【i,j】 全部加1。 最后查询从头到尾遍历一遍找到最大的paint【i】就可以了。

这个题目由于数据规模小可以直接这样做。

当数据规模较大的时候,每次染色的最大消耗将是 从0~n;


这里学到了一个巧妙地办法


为区间 【i, j】 染色,我们只要将 paint【i】++ ;paint【j+1】-- ;统计染色次数只要从0向终点求和即可,复杂度为O(n)。

直接这样描述不好懂,我们来举个栗子。

给定区间 1 - 4 ,染色后:

      i:         1 2 3  4 5 6 7

paint【i】:1 0 0 0 -1 0 0

可以看出 sum【1】 =1 , sum【2】 =1 ,sum【3】 =1,sum【4】 = 1,sum【5】 = 0;

给定区间 4 - 6 ,染色后:

      i:         1 2 3  4 5 6 7

paint【i】:1 0 0 0 0 0 -1

这时,sum【1】 =1 , sum【2】 =1 ,sum【3】 =1,sum【4】 = 1,sum【5】 = 1,sum【6】 = 1, sum【7】=0;

这样我们就实现了只用给 paint【i】和paint【j+1】 赋值 ,就实现了染色次数的统计 。 省去了O(n)时间的染色阶段。


【普通的染色方法】

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 24*3610;
int ans[maxn];
int main(){
	int n;
	while(scanf("%d",&n)!=EOF&&n){
		int a,b;
		memset(ans,0,sizeof(ans));
		int begin = 1,end=1;
		for(int i=0;i<n;i++){
			scanf("%d%d",&a,&b);
			if(b>end)
				end = b;
			for(int j=a;j<=b;j++){
				ans[j]++;
			}
		}
		int maxx =1;
		for(int i=0;i<=end;i++){
			maxx = max(maxx,ans[i]);
		}
		printf("%d\n",maxx);
	}
	return 0;
}


【欧阳大神教的染色方法】

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 24*3610;
int paint[maxn];
int main(){
	int n;
	while(scanf("%d",&n)!=EOF && n){
		int a,b;
		int maxx = 1;
		memset(paint,0,sizeof(paint));
		for(int i=0;i<n;i++){
			scanf("%d%d",&a,&b);
			if(b>maxx)
				maxx = b;
			paint[a]++;
			paint[b+1]--;
		}
		int sum = 0;
		int ans = 0;
		for(int i=0;i<=maxx;i++){
			sum += paint[i];
			ans = max(sum,ans);
		}
		printf("%d\n",ans);
	}
	return 0;
}


【这里还有个贪心的算法】

开始我是按照演出结束时间排序的WA了,以开始时间排序AC了,还没有想明白为什么。希望各路大神的指点可怜

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<set>
#include<vector>
const int maxn = 110;
using namespace std;
string num[maxn];
bool vis[maxn];
struct Node{
	int x,y;
}node[maxn];
bool cmp(const Node&a, const Node&b){
	if(a.x == b.x)
		return a.y<b.y; 
	return a.x<b.x; //以开始时间小的排序
}
int main(){
	int n;
	while(scanf("%d",&n)!=EOF &&n){
		for(int i=0;i<n;i++){
			scanf("%d%d",&node[i].x,&node[i].y);
		}
		memset(vis,0,sizeof(vis));
		sort(node,node+n,cmp);
		int sign = n;
		int ed = 0;
		int day = 0;
		while(sign){
			day ++;
			vis[ed] = 1;
			sign--;
			int tmpx = node[ed].y;
			for(int i=0;i<n;i++){
				if(!vis[i] && node[i].x>tmpx){
					vis[i] = 1;
					tmpx = node[i].y;
					sign--;
				}
			}
			for(int i=0;i<n;i++){
				if(!vis[i]){
					ed = i;break;
				}
			}
		}
		printf("%d\n",day);
	}
	return 0;
}



转载于:https://www.cnblogs.com/chaiwenjun000/p/5321167.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值