CodeForces - 589F

美食家的最优用餐策略
本文介绍了一道算法题的解决思路,美食家要在有限时间内品尝尽可能多的菜品,每道菜品都有上桌和下桌的时间限制。通过构建菜品结构体、排序及二分查找等方法,最终求出美食家在宴会上吃菜的最大总时间。

题目链接:http://codeforces.com/problemset/problem/589/F

题目翻译:

一个美食家走进宴会厅,厨师向客人推荐了n道菜。美食家知道每道菜的时间安排:每道菜何时上桌。
对于第i道菜,他在ai和bi(宴会开始后的几秒钟)的时间里知道了两个整数的时刻——厨师将第i道菜端进大厅,何时端出(ai < bi)。例如,如果ai = 10, bi = 11,那么第i道菜可以在一秒钟内吃完。
这些菜的数量很多,所以保证只要这道菜可以吃(即在大厅里),就不会用完。
美食家想尝试这n道菜肴,而不是冒犯任何厨师。正因为如此,美食家们想要在同样的时间里吃每一道菜。在吃的过程中,美食家可以立即在菜肴之间切换。他只允许在整数时刻在盘子之间切换。美食家只能同时吃一道菜。它可以在吃完其他的菜后再回到盘子里。
美食家希望在宴会上吃得尽可能久,不违反上述任何条件。你能帮他找出他在宴会上最多能吃多少菜吗?
输入
输入的第一行包含一个整数n(1≤n≤100)-宴会菜肴的数量。
以下n行包含了关于菜肴可用性的信息。第i个行包含两个整数ai和bi(0≤ai < bi≤10000)——瞬间变为可用时的第i个菜吃,当第i个菜就是离开大厅。
输出
输出必须包含唯一的整数-美食家在宴会上吃菜的最大总时间。
美食家可以即时地在菜肴之间切换,但只在整数时刻。它可以在吃完其他的菜后再回到盘子里。而且在每一个时刻,他只能吃一道菜。

解题思路:首先构建一个结构体,结构体的里定义每道菜的上菜时间与结束 时间,按照结束时间将其排序,定义一个visit数组,表示该时刻是否在食用某道菜,找到每道菜的可能的食用时间1<=t<=maxs(所有菜可食用的时间的最小值)在这个区间进行二分,找到能够符合题意的最大的值想x,最后输出x*n;

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=105;
struct st
{
	int bn,en;
	bool operator <(const st& a)
	{
		if(en!=a.en)
		return en<a.en;
		else
		return bn<a.bn;
	}
}stm[maxn];
int maxs=inf,ans=0;
int visit[10100],n;
bool jug(int a)
{
	memset(visit,0,sizeof(visit));
	int i,j,cnt;
	for(i=0;i<n;i++)
	{
		cnt=0;
		if(stm[i].en-stm[i].bn>=a)
		{
			for(j=stm[i].bn;j<stm[i].en;j++)
			{
				if(!visit[j])
				{
					cnt++;
					visit[j]=1;
				}
				if(cnt==a)
				{
				//	printf("j:%d cnt:%d\n",j,cnt);
					break;
				}
			}
		}
		else
		return false;
		if(cnt!=a)
		return false;
	}
	return true;
}
void bin_search()
{
	int l,r;
	l=1;
	r=maxs;
	int mid;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(jug(mid))
		{
			ans=mid;
		//	printf("l:%d r:%d mid:%d\n",l,r,mid);
			l=mid+1;
		}
		else
		r=mid-1;
	}
} 
int main()
{
	int i;
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		scanf("%d%d",&stm[i].bn,&stm[i].en);
		maxs=min(maxs,stm[i].en-stm[i].bn);
	}
	sort(stm,stm+n);
	bin_search();
	printf("%d",ans*n);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值