poj 3616 Milking Time 赋权区间调度问题 动态规划

题目链接
描述

贝茜就是这样一头勤劳的奶牛。事实上,她非常专注于最大限度地提高自己的工作效率,以至于她决定安排下一个N(1≤N≤1,000,000)小时产生尽可能多的乳汁。

农夫约翰有一个M(1≤M≤1,000)的列表,这些间隔可能重叠,他可以在其中挤奶。每个间隔 i 有一个开始小时 (0 ≤ starting_hour i ≤ N),一个结束小时 (starting_hour i < ending_hour i ≤ N) 和相应的效率 (1 ≤ efficiency i ≤ 1,000,000),这表明他在该间隔内可以从 Bessie 获得多少加仑牛奶。农夫 John 分别在开始时间和结束时间开始时开始和停止挤奶。挤奶时,必须将 Bessie 挤奶整个间隔。

不过,即使是贝茜也有她的局限性。在任何间隔期间挤奶后,她必须休息R(1≤R≤N)小时,然后才能再次开始挤奶。给定农夫约翰斯的间隔列表,确定贝茜在N小时内可以产生的最大牛奶量。

输入

  • 第 1 行:三个空格分隔的整数:N、M 和 R
  • 第 2 行-M+1行:i+1 行描述了第 i 个挤奶间隔,有三个空格分隔的整数:starting_hour i、ending_hour i 和 efficiency i

输出

  • 第 1 行:Bessie 在 N 小时内可以生产的最大加仑牛奶数

示例输入

12 4 2
1 2 8
10 12 19
3 6 24
7 10 31
示例输出

43

这是一个赋权区间调度问题,需要用动态规划解决。首先用一个结构体存储每个区间的开始时间、结束时间和权值,然后将区间按照结束时间的升序排序。
设p(j)为与活动j相容且结束时间不晚于start j的结束时间最晚的任务,首先用循环找到每个活动的p(j)。
设OPT(j)为活动1,2……j对应的最优解,每一步有以下两种情况:
(1)最终最优解包含j,则OPT(j)=OPT(p(j))+vj,即j的前一个最晚相容解加上j的权值
(2)最终最优解不包含j,则OPT(j)=OPT(j-1)
由此可以得到动态规划的递推公式:
OPT(j)=0 j=0
OPT(j)= max(vj+OPT(p(j)),OPT(j-1)) j≠0

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
struct interval{
	int start;
	int finish;
	int eff;
};
bool cmp(interval a,interval b){
	if(a.finish==b.finish) return a.start<b.start;
	return a.finish<b.finish;
}

interval inter[1005];
int p[1005],ma[1005];
int main(){
	int n,m,r,i,j;
	cin>>n>>m>>r; //这里的n其实是用不到的,输入进来就行
	for(i=1;i<=m;i++){
		cin>>inter[i].start>>inter[i].finish>>inter[i].eff;
	}
	sort(inter+1,inter+1+m,cmp);
	for(i=m;i>=1;i--){
		for(j=m-1;j>=1;j--){
			if(inter[j].finish+r<=inter[i].start){//注意这里奶牛每工作完一个时间段需要休息r小时,所以寻找p[i]时需要加上r
				p[i]=j;
				break;
			}
		}
		if(j==0) p[i]=0;
	}
	ma[0]=0;
    for(i=1;i<=m;i++){
    	ma[i]=max(ma[i-1],ma[p[i]]+inter[i].eff);
    	
	}
	cout<<ma[m]<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值