Milking Time
题目大意:
给你m个时间段,每个时间段包括一个开始时间和一个结束时间,另外还有一个价值,现在要你在连续的n时间内找到互不相交区间间隔相差r且完整的区间,使得价值和最大,输出价值和。
数据范围:
1≤m≤1000,1≤n≤1000000,0≤startinghouri<endinghouri≤n,1≤r≤n。 1 ≤ m ≤ 1000 , 1 ≤ n ≤ 1000000 , 0 ≤ s t a r t i n g h o u r i < e n d i n g h o u r i ≤ n , 1 ≤ r ≤ n 。
解题思路:
这个题呢,有个值得注意的点,如果没有注意到这个点题目就很难(我不会),那么要看见了的话就比较简单可想了,就是要注意到开始时间和结束时间都小于n,我开始以为仅仅只是小于1e6而已,那么这个题n就没有什么用处了,也就是这个限制条件并没有什么用,迷惑而已。那么就可以这么想,在将开始时间按从小到大排序之后,dp[i]代表选第i个后最大价值,那么第i个可以由之前的dp[1~i-1]转移过来,满足条件就加入状态并维护一个最大值,所以状态转移方程就为:
if(dp[j].r+r<=dp[i].l)dp[i]=max(dp[i],dp[j]+num[i].w).
i
f
(
d
p
[
j
]
.
r
+
r
<=
d
p
[
i
]
.
l
)
d
p
[
i
]
=
m
a
x
(
d
p
[
i
]
,
d
p
[
j
]
+
n
u
m
[
i
]
.
w
)
.
AC代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn = 1000;
int dp[maxn + 5];
struct NOOD {
int l, r, w;
}num[maxn + 5];
int n, m, r, Max;
bool cmp(NOOD x, NOOD y) {return x.l < y.l;}
int main() {
scanf("%d%d%d", &n, &m, &r);
for(int i = 1; i <= m; i++)scanf("%d%d%d", &num[i].l , &num[i].r, &num[i].w);
sort(num + 1, num + m + 1, cmp);
for(int i = 1; i <= m; i++) {
dp[i] = num[i].w;//要么前面一个不要,即从自己开始
for(int j = 1; j < i; j++)//要么从之前的状态找一个最大的
if(num[j].r + r <= num[i].l)
dp[i] = max(dp[i], dp[j] + num[i].w);
}
Max = 0;
for(int i = 1; i <= m; i++)Max = max(Max, dp[i]);
printf("%d\n", Max);
return 0;
}