当前位置: 首页 > article >正文

P2889 [USACO07NOV] Milking Time S

题目大意

N N N 个小时可以挤奶。其中有 m m m 个时间段可以给 Bessis 奶牛挤奶。第 i i i 个时间段为 s i s_i si ~ t i t_i ti,可以获得 E f f i Eff_i Effi 滴奶。每次挤完奶后,人都要休息 R R R 小时。最后问,一共能挤出多少滴奶。

双重选择分析

休息 R R R 小时可以归为挤奶时间段内。即,第 i i i 段挤奶的时间段为 s i s_i si ~ t i = t i + R t_i=t_i+R ti=ti+R

设挤奶的最佳方案为:
{ a 1 , a 2 , . . . , a k } \{a_1,a_2,...,a_k\} {a1,a2,...,ak},其中 a i a_i ai 是第 i i i 个挤奶的时间段编号。同时满足 s a 2 ≥ t a 1 s_{a_2}\ge t_{a_1} sa2ta1 s a 3 ≥ t a 2 s_{a_3}\ge t_{a_2} sa3ta2,以此类推。

显然,为了更好的选奶牛,要对奶牛按 t i t_i ti 进行排列。

a k a_k ak 进行双重选择分析:

  • a k = m a_k=m ak=m,方案变为 { a 1 , a 2 , . . . , a k − 1 , m } \{a_1,a_2,...,a_{k-1},m\} {a1,a2,...,ak1,m}方案的属性:

    1. 奶量。原方案的奶量 = 子方案的奶量 + E f f m Eff_m Effm。由于,原方案求的是最大奶量,所以子方案求解的也是最大奶量。
    2. 可以选择的时间段范围。子方案可以选择的范围为 1 ~ m − 1 m-1 m1
    3. 奶牛最大的挤奶结束时间。子方案奶牛最大的挤奶结束时间为 s m s_m sm

    综上,子方案反映的问题为,从 1 ~ m − 1 m-1 m1 个时间段中,挤奶结束时间最大为 s m s_m sm 的最大奶量问题。

  • a k ≠ m a_k≠m ak=m,方案不变。
    方案的属性:

    1. 奶量。原方案的奶量 = 子方案的奶量。
    2. 可以选择的时间段范围。子方案可以选择的范围为 1 ~ m − 1 m-1 m1
    3. 奶牛最大的挤奶结束时间。子方案奶牛最大的挤奶结束时间为 N N N

    综上,子方案反映的问题为,从 1 ~ m − 1 m-1 m1 个时间段中,挤奶结束时间最大为 N N N 的最大奶量问题。

综上,原问题的状态描述为 d p m , N dp_{m,N} dpm,N状态转移式为 d p m , N = max ⁡ ( d p m − 1 , s n + E f f m , d p m − 1 , N ) dp_{m,N} = \max(dp_{m-1,s_n}+Eff_m,dp_{m-1,N}) dpm,N=max(dpm1,sn+Effm,dpm1,N)

将其一般化可得 d p i , j = max ⁡ ( d p i − 1 , s i + E f f i , d p i − 1 , j ) dp_{i,j}=\max(dp_{i-1,s_i}+Eff_i,dp_{i-1,j}) dpi,j=max(dpi1,si+Effi,dpi1,j)需要注意的是:第一种情况只有当 t i ≤ j t_i\le j tij 的时候才成立。

这样做,最终的时间复杂度、空间复杂度都为 O ( n m ) O(nm) O(nm),只能拿到 70 分。

示例程序

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 1e3 + 10;

struct node{
	int s,t,eff;
	bool operator < (const node &p)const{
		return t < p.t;
	}
}cow[N];

int dp[N][N * 100];



int main(){
	int n,m,r;
	cin >> n >> m >> r;
	
	n += r;
	for(int i = 1; i <= m; i++){
		cin >> cow[i].s >> cow[i].t >> cow[i].eff;
		cow[i].t = cow[i].t + r;
	}
	
	sort(cow + 1,cow + m + 1);
	
	for(int i = 0; i <= n; i++){
		if(i >= cow[1].t) dp[1][i] = cow[1].eff;
		else dp[1][i] = 0;
	}
	
	for(int i = 2; i <= m; i++){
		for(int j = 0; j <= n; j++){
			if(j >= cow[i].t){
				dp[i][j] = dp[i - 1][cow[i].s] + cow[i].eff;
			}
			dp[i][j] = max(dp[i][j],dp[i - 1][j]);
		}
	}
	
	cout << dp[m][n];
	
	
	
	
	return 0;
}

http://www.kler.cn/a/560188.html

相关文章:

  • EasyExcel 实践案例:打印工资条
  • 【NLP 38、激活函数 ④ GELU激活函数】
  • Deepseek引爆AI热潮 防静电地板如何守护数据中心安全
  • 卸载Mysql重装(升级版本)
  • UE5网络通信架构解析
  • ubuntu+aarch64+dbeaver安装【亲测,避坑】
  • 基于 Python 的项目管理系统开发
  • db.session.delete是什么意思
  • 【R包】tidyplots----取代ggplot2的科研绘图利器
  • pytest-html
  • TMDS视频编解码算法
  • git 命令 设置别名
  • 《操作系统 - 清华大学》 8 -8:进程管理:为什么使用线程
  • 【Python爬虫(63)】从0到1:打造图片与视频爬虫攻略
  • 【java】implements
  • 原子操作、写回策略、缓存一致性问题、内存序详解
  • Vue面试2
  • 三、《重学设计模式》-单例模式
  • Python - 代码片段分享 - Excel 数据实时写入方法
  • uniapp打包生产证书上架IOS全流程