Hdu 4502 吉哥系列故事——临时工计划(DP)

1003吉哥系列故事——临时工计划

Time Limit: 1.0 Seconds   Memory Limit: 32768K

 

 

俗话说一分钱难倒英雄汉,高中几年下来,吉哥已经深深明白了这个道理,因此,新年开始存储一年的个人资金已经成了习惯,不过自从大学之后他不好意思再向大人要压岁钱了,只能把唯一的希望放到自己身上。可是由于时间段的特殊性和自己能力的因素,只能找到些零零碎碎的工作,吉哥想知道怎么安排自己的假期才能获得最多的工资。

已知吉哥一共有m天的假期,每天的编号从1到m,一共有n份可以做的工作,每份工作都知道起始时间s,终止时间e和对应的工资c,每份工作的起始和终止时间以天为单位(即天数编号),每份工作必须从起始时间做到终止时间才能得到总工资c,且不能存在时间重叠的工作。比如,第1天起始第2天结束的工作不能和第2天起始,第4天结束的工作一起被选定,因为第2天吉哥只能在一个地方工作。

现在,吉哥想知道怎么安排才能在假期的m天内获得最大的工资数(第m+1天吉哥必须返回学校,m天以后起始或终止的工作是不能完成的)。

 

Input

 

第一行是数据的组数T;
每组数据的第一行是2个正整数:假期时间m和可做的工作数n;
接下来n行分别有3个正整数描述对应的n个工作的起始时间s,终止时间e,总工资c。

 

[Technical Specification]

1<=T<=1000

9<m<=100

0<n<=1000

s<=100, e<=100, s<=e

c<=10000

 

Output

对于每组数据,输出吉哥可获得的最高工资数。

 

SampleInput

1

10 5

1 5 100

3 10 10

5 10 100

1 4 2

6 12 266

 

SampleOutput

102

 

一打眼看这道题,以为是贪心,但是后来仔细一分析,发现是dp

用dp[i]记录前i天的最大收入,那么dp[m]就最后的解。详细的解析,看代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N = 110;

vector <int> s[N]; //用来存储每个结束时间,所对应的开始时间,根据输入,一个结束时间可能会有对应几个开始时间,和几个工资
vector <int> c[N]; //用来存储每个结束时间,所对应的工资,根据输入,每个结束时间可能会对应不同的工作和工资
int n, m, dp[N];   //dp[i]用来存储第i天挣得最多的钱
int x, y, z, T;

int main()
{
    scanf("%d", &T);
    while ( T-- ) {
        scanf("%d%d", &n, &m);
        for ( int i = 0; i <= n; ++i ) {
            s[i].clear();
            c[i].clear();
            dp[i] = 0;      //初始化为0
        }
        for ( int i = 0; i < m; ++i ) {
            scanf("%d%d%d", &x, &y, &z);
            if ( x > y ) continue;
            if ( x < 1 ) continue;
            if ( x > n || y > n ) continue;
            s[y].push_back(x);
            c[y].push_back(z);
        }
        for ( int i = 1; i <= n; ++i ) {
            dp[i] = dp[i-1];    //将dp[i] 复制为dp[i-1] ,这一步不能省,因为如果第i天不是任何的工作的截止日期,那么它能赚的钱数就没有变,等于dp[i-1]i, 并且s[i]是空的不会进入接下来的循环
            for( int j = 0; j < s[i].size(); ++j ) 
                dp[i] = max( dp[i], dp[s[i][j]-1]+c[i][j] ); //如果i是某一个工作的结束日期,那么就要比较选择这个工作和不选择这个工作那个赚的比较多;然后一定是d[i]来比较,而不是d[i-1],这个要注意,在每一次循环后,dp[i]的值都可能改变;后面的是如果选择了这一天,那么赚的钱就是做这个工作的前一天的总工资加这个工作的工资
            //printf("%d %d\n", i, dp[i]);
        }
        printf("%d\n", dp[n]);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值