poj 3616

题意: 给奶牛挤奶,共有n小时,有m次可以挤,给出每次开始挤奶的时间s,结束挤奶的时间e,还有挤奶的量f,每次挤完奶要休息r时间,问最大挤奶量.

有两种思路,
一. LIS的变形,
dp[i]表示以第i个节点结尾的最优解
1. dp[i]有两种情况,第一是的max(dp[i],d[i].f),第二就是max(dp[i],dp[j]+d[i].f),我刚开始以为if (d[i].s >= d[j].e + r) ,就是max(dp[i],dp[j]+d[i].f),else就是max(dp[i],d[i].f),其实不是这样。因为第二层循环不会刷新dp[0],所以如果dp[1]没有使用dp[0],那么d[0]的数据就会被省略,造成错误,非要这么写的话,应该在最前面对dp[0]赋值。
2. 我刚开始以为直接输出dp[m-1],dp数组的定义是以第i个节点结尾的最佳解,所以真正的最佳解有可能在中间,

#include <iostream>
#include <cstdio>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <stack>
#include <stdlib.h>
#include <stdio.h>

#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define l(x) (x<<1)
#define r(x) (x<<1|1)
#define ms(a,b) memset(a,b,sizeof(a))

using namespace std;

struct node {
	int s, e,f;
	friend bool operator<(const node&a, const node&b) {
		return a.s < b.s;
	}
};

int n, m, r,len,res;
node d[1111111];
int dp[1111111];

int main() {
	ios::sync_with_stdio(false);
	cin >> n >> m >> r;
	for (int i = 0; i < m; i++) {
		cin >> d[i].s>> d[i].e>> d[i].f;
	}

	sort(d, d + m);

	ms(dp, 0);
	//for(int i = 0; i < m; i++) dp[i] = d[i].f;
	dp[0] = d[0].f;
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < i; j++) {
			if (d[i].s >= d[j].e + r) {
				dp[i] = max(dp[i], dp[j] + d[i].f);
			}
			else {
				dp[i] = max(dp[i], d[i].f);
			}
		}
		res = max(res, dp[i]);
	}
	cout << res << endl;

	return 0;
}

二.普通的dp

dp[i]表示i时刻的最优解

  1. 上面出现的问题,
  2. 对于node的排序,应该是结束时间排序,而不是开始时间排序
#include <iostream>
#include <cstdio>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <stack>
#include <stdlib.h>
#include <stdio.h>

#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define l(x) (x<<1)
#define r(x) (x<<1|1)
#define ms(a,b) memset(a,b,sizeof(a))

using namespace std;

struct node {
	int s, e,f;
	friend bool operator<(const node&a, const node&b) {
		return a.e < b.e;
	}
};

int n, m, r,len,res;
node d[1111111];
int dp[1111111];

int main() {
	ios::sync_with_stdio(false);
	cin >> n >> m >> r;
	for (int i = 0; i < m; i++) {
		cin >> d[i].s>> d[i].e>> d[i].f;
	}

	sort(d, d + m);

	ms(dp, 0);
	for(int i = 0; i < m; i++) dp[d[i].e] = d[i].f;
	len = 0;
	for (int i = 0; i <= n; i++) {
		dp[i] = dp[i - 1];
		for (; len < m && d[len].e <= i; len++)
			if (i > r)
				dp[i] = max(dp[i], dp[d[len].s - r] + d[len].f);
			else
				dp[i] = max(dp[i], d[len].f);
		res = max(res, dp[i]);
	}

	cout << res << endl;

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值