2019 BUPT Winter Training #1 div2 E - E//CodeForces - 597B

总算遇到个能写的题了。
也忒巧了,这两天刚好在看趣学算法,刚好看到贪心(其实就是第一章Orz),刚好学了个题,刚好就跟这个几乎一样,只不过取等不一样,问题背景不同。
其实把这些订单时间以时间为横轴拼起来,就是一堆可能有重叠的的线段,我们的目的就是找若干条线段,使其不重叠地拼起来,而且线段的数量最多。
这是一个典型的贪心问题。
按照人处理这个问题的直觉,贪心策略可能有三个。引自趣学算法
1.每次从剩余订单中取时间最短的订单来处理。
缺陷:时间最短的订单的起始时间是不知道的,万一最短的刚好是今天最晚的订单,那不就只能处理一个了。
2.每次从剩余订单中取开始时间最早的来处理。
缺陷:开始时间最早的订单的持续时间是不知道的,万一一个订单从早搞到晚,那一天也只能处理一个。
3.每次从剩余订单中取结束时间最早的来处理。
这样的贪心策略是最好的,因为结束时间是由开始时间和持续时间共同决定的,要处理订单时,处理结束时间最早的订单就一定能留下最多的时间。
C++:

#include <iostream>
#include <algorithm>
using namespace std;
typedef struct _order
{
	int beg;
	int end;
}order;//定义订单结构体,包含开始时间和结束时间

bool modifiedSort(order a,order b)
{
	if(a.end==b.end)
		return (a.beg>b.beg);
	else return (a.end<b.end);
}//自定义排序,优先选择结束早的,如果两者结束时间都一样,那就取开始时间大的(开始得晚的),保证可以支配的时间最多。
//返回a是否比b更优,是则true,否则false
int main(int argc, char const *argv[])
{
	int n;cin>>n;
	order arr[n];//定义结构体数组
	for(int i=0,j;i<n;i++)
		cin>>arr[i].beg>>arr[i].end;
//之前读入结构体数组时栽了个跟头,每次读取的是一个结构体的两个数据
//i遍历的是结构体数组,不需要再用另一个变量来遍历什么了
	sort(arr,arr+n,modifiedSort);//调用C++自带的快排来排序,排序依据是自定义的排序
	//现在结构体数组arr已经被排序过了,和原来已经不一样了,现在按0,1,2...,结束时间是逐渐增加的。
	int cnt=1,last=arr[0].end;//last标记最后完成的订单的结束时间,cnt标记订单完成个数
	for(int i=1;i<n;i++)
		if(arr[i].beg>last)//如果下一个订单的开始时间比上一个的结束时间迟(不可重叠),就可以做
		{
			cnt++;
			last=arr[i].end;
		}
	cout<<cnt<<endl;
	return 0;
}

还提供一组

过不了的

C语言版本
其实不是代码的问题,我不会写快速排序(O(nlogn)),只能用冒泡排序O(n^2)代替,最后TLE。
所以尽量看C++的版本,其实C++和C语法也差不了太多。

#include <stdio.h>
typedef struct _order
{
	int beg;
	int end;
}order;

int modifiedSort(order a,order b)
{
	if(a.end==b.end)
		return (a.beg>b.beg);
	else return (a.end<b.end);
}

int main(int argc, char const *argv[])
{
	int i,j,cnt,last,n,tmp;
	scanf("%d",&n);
	order arr[n];
	int aux[n];//辅助数组,用于嵌套排序
	for(i=0;i<n;i++) aux[i]=i;
	for(i=0;i<n;i++)
		scanf("%d%d",&arr[i].beg,&arr[i].end);
	for(i=1;i<n;i++)
		for(j=0;j<n-i;j++)
			if(!modifiedSort(arr[aux[j]],arr[aux[j+1]]))
			{
				tmp=aux[j];
				aux[j]=aux[j+1];
				aux[j+1]=tmp;
			}
	cnt=1;
	last=arr[aux[0]].end;
	for(i=1;i<n;i++)
		if(arr[aux[i]].beg>last)
		{
			cnt++;
			last=arr[aux[i]].end;
		}
	printf("%d",cnt);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值