POJ - 3616 DP

Milking Time

题目大意:

给你m个时间段,每个时间段包括一个开始时间和一个结束时间,另外还有一个价值,现在要你在连续的n时间内找到互不相交区间间隔相差r且完整的区间,使得价值和最大,输出价值和。

数据范围:

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]转移过来,满足条件就加入状态并维护一个最大值,所以状态转移方程就为:
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;
}

猜你喜欢

转载自blog.csdn.net/qq_36889101/article/details/80138613