POJ 3616题目大意如下:
又是FJ和他的牛,FJ给牛指定了产奶时间段,每个时间段内,牛在不停的产奶,当这个时间段完结后,牛需要R时间休息。给出M个时间段,和指定的间隔休息时间,以及每个产奶时间段产奶数量,求产奶的最大值。
终于自己AC了一个dp,但是还是wrong了两次(不细心,把M当成了R)。简单dp的基本就是写出状态转移方程,dp数组对应0到第j段产奶时间短的最末时间,表示整个区间,因此对于考虑的第i段,和第j段有如下关系:
如果指定区间和参考段没有时间重叠那么就有dp[i] = dp[j] + Seg[i].efficient
当然如果此值比dp[i]小,那就不更新,即有:dp[i] = max(dp[i], dp[j] + Seg[i].efficient)
可能会想,这样做会把某些区间和参考段重合的情况忽视了,但是这样更新的另一个原因是:这些重合区间是包含之前区间情况的,而且由于dp是对应一个个时间段,所以如果后面重叠时间段实际的情况是不重叠时间段的话,实际这种情况就是不重叠时间段(之前已经有了)
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long int LL;
const int maxn = 1000;
struct Milking {
int start, end;
int efficent;
}Seg[maxn + 3];
int N, M, R;
LL dp[maxn + 3];
bool camp(const Milking& lhs, const Milking& rhs) {
return lhs.start < rhs.start || (lhs.start == rhs.start && lhs.end < rhs.end);
}
void solve() {
LL ans = 0;
sort(Seg, Seg + M, camp);
for (int i = 0; i < M; i++) dp[i] = Seg[i].efficent;
for (int i = 0; i < M; i++) {
for (int j = 0; j < i; j++) {
if (Seg[j].end + R <= Seg[i].start)
dp[i] = max(dp[i], dp[j] + Seg[i].efficent);
}
ans = dp[i] > ans ? dp[i] : ans;
}
printf("%lld\n", ans);
}
int main(int argc, const char * argv[]) {
// insert code here...
scanf("%d %d %d", &N, &M, &R);
for (int i = 0; i < M; i++) scanf("%d %d %d", &Seg[i].start, &Seg[i].end, &Seg[i].efficent);
solve();
return 0;
}
Accept 712K/32MS