2017ICPC北方邀请赛H题 MJF wants to work(贪心)

石油大提交网址:http://exam.upc.edu.cn/problem.php?id=4203

4203: MJF wants to work

时间限制: 1 Sec  内存限制: 128 MB
提交: 60  解决: 11
[提交][状态][讨论版]

题目描述

MJF feel the summer vacation is very leisure. So he wants to work to earn money.
There are n jobs MJF can take part in.For job i, it has the start time ti.x, the end time ti.y and reward ci.
MJF wants to take part in two jobs (exact two jobs), and he wants to earn exactly M yuan. He doesn't want to earn one money more,he thinks it's a waste.
Becase MJF is a lazy boy, so he wants the time of the sum of two jobs shortest.
Becase MJF can only take part in one job in a time.So two jobs can't overlap.(ti.y < tj.x)

输入

The input consists of multiple test cases. 
For each test,the first line contains 2 integers n, m.(1 <= n, m <= 2e5)
Then following n lines, each line contains 3 integers ti.x, ti.y, ci.(1 <= ti.x, ti.y, ci <= 2e5)

输出

For each test case, print the value of the sum of two jobs' time.if there are no answer,please print"oh no!"

样例输入

3 10
1 2 3
3 4 7
4 6 7
1 10
1 10 10

样例输出

4
oh no!

【解析】:

把每一个区间的左右端点拆开,但要两端点都记住自己的money和time。

然后按时间先后排序,扫一遍,此过程中,遇到右端点,就存一下此工作结束后的钱数与所用时间(最小值)

这里用的是dp数组。dp[i]表示挣钱为i的工作所用的时间(最小)。

遇到左端点,就把这项工作与前面已经扫过的工作组合,加一下时间,不断更新ans(最小)

【代码】:

#include <stdio.h>
#include <stdlib.h>  
#include <string.h>  
#include <algorithm> 
#define mset(a,i) memset(a,i,sizeof(a))
using namespace std;
const int INF=0x3f3f3f3f;
const int MAX=1e6+5;
struct node{
	int p,flag;
	int money;
	int time;
}e[MAX*4];
int dp[MAX*2];
int n,m,cnt;
void add(int l,int r,int val)
{
	e[cnt].p=l;
	e[cnt].flag=0;//左端点 
	e[cnt].money=val;
	e[cnt].time=r-l+1;
	cnt++;
	e[cnt].p=r;
	e[cnt].flag=1;//右端点 
	e[cnt].money=val;
	e[cnt].time=r-l+1;
	cnt++;
}
bool cmp(node a,node b)
{
	if(a.p==b.p)return a.flag<b.flag;//若左右端点同点,先处理左; 
	return a.p<b.p;//按端点排序 
}
int solve()
{
	sort(e,e+cnt,cmp);
	mset(dp,INF);//dp[i]记录当赚钱为i时,所用的最小时间
	int ans=INF;
	for(int i=0;i<cnt;i++)
	{
		if(e[i].flag==0)//左
		{
			ans=min(ans,dp[m-e[i].money]+e[i].time);
		}
		else
		{
			dp[e[i].money]=min(dp[e[i].money],e[i].time);
		}
	}
	return ans;
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		cnt=0;
		for(int i=0;i<n;i++)
		{
			int l,r,val;
			scanf("%d%d%d",&l,&r,&val);
			add(l,r,val);
		}
		int ans=solve();		
		if(ans==INF)
			puts("oh no!");
		else
			printf("%d\n",ans);
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪的期许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值