sicily1750. 运动会

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

ZEH是一名04级的学生,他除了绩点高,还有运动细胞。有一次学院举办运动会,ZEH发现里面的项目都是他所向披靡的,当然他想获得所有项目的No1,但是一个人的精力总是有限的,ZEH也是只有P(Power的简写,一个大于0且小于1000的整数)的精力。如果精力足够参加比赛,一定能赢;相反,精力不够去参加比赛,Loss的概率很大,ZEH当然不想因为Loss而不爽。

整个运动会有N(大于0且小于等于100)项比赛,每项比赛都是在指定的一天D(D大于等于0)内举行完,但是一天可能同时有多个比赛同时进行,ZEH当然就不能同时兼顾。比赛结束后,院长都会亲自为冠军颁发一定数额的奖金,其他名次只有一张奖状。ZEH当然是冲着奖金去的,他想获得最多的奖金,师弟师妹们,你能帮ZEH大牛计算出他最多能拿多少奖金吗?

Input

第一行是一个整数T,表示这题有T个用例。
每个用例的第一行有两个正整数P N,分别表示ZEH的精力和比赛的项目。
第二行到第N+1行是N个项目,每一行有三个正整数D E M,分别表示这个项目在第D天举行,需要E的精力,和比赛的奖金。项目的顺序都按D排好序。

Output

对于每个用例,输出他能拿的最多的奖金。

Sample Input

1
14 5
0 3 7
0 2 5
1 4 2
2 6 14
2 8 15

Sample Output

23
 
  
 
  
    分析:这道题目,一看好像是DP问题,认真看下去,确实是DP问题,只不过这个DP问题比一般的背包问题稍微复杂一点点,这个是背包问题的延伸。
    可以这样来理解题目意思,首先按照精力DP,内部循环是每一天的DP,每一天里面又包括多个活动,故每一天里面也要进行一次枚举,把所有的活动都过一遍。
    处理这道题目的关键,首先要读懂题目意思,知道这是一道DP问题,然后,设计好实用的数据结构。最后,实现起来就比较简单了。

#include <iostream>
#include <cstring>
#include <string>
#include <stdio.h>
#include <vector>
#include<memory.h>
using namespace std;

struct Node{
    int power[101];
    int money[101];
    int size;
};
int max(int a, int b) {
    if (a >= b) {
        return a;
    }
    else
        return b;
}
int main() {
    int t;
    scanf("%d", &t);
    int p, n, d, e, m;
    while (t --) {
        scanf("%d%d", &p, &n);
        Node node;
        int md = -1;
        int tempsize;
        vector<Node> myv;
        for (int i = 1; i <= n; ++ i) {
            scanf("%d%d%d", &d, &e, &m);
            if (md != d) {
                md = d;
                tempsize = 0;
                node.power[tempsize] = e;
                node.money[tempsize] = m;
                node.size = 1;
                myv.push_back(node);
            }
            else if (md == d) {
                //node = myv[d]
                tempsize = myv[myv.size() - 1].size;
                myv[myv.size() - 1].power[tempsize] = e;
                myv[myv.size() - 1].money[tempsize] = m;
                ++ myv[myv.size() - 1].size;
            }
        }
        int dp[p + 1][myv.size() + 1];
        memset(dp, 0, sizeof(dp));
//cout << myv.size() << endl;
        for (int i = 1; i <= p; ++ i) {
            for (int j = 1; j <= myv.size(); ++ j) {
                //cout << "www" << j << endl;
                int maxu = -9;
                for (int k = 0; k < myv[j - 1].size; ++ k) {
                    if (myv[j - 1].power[k] <= i) {
                        dp[i][j] = max (dp[i][j - 1], dp[i - myv[j - 1].power[k]][j - 1] + myv[j - 1].money[k]);
                            //cout <<"a "<< i << " " << j << " " << dp[i][j] << endl;
                            if (dp[i][j] > maxu) {
                                maxu = dp[i][j];
                            }
                    }
                    else {
                        dp[i][j] = dp[i][j - 1];
                        //cout <<"b "<< i << " " << j << " " << dp[i][j] << endl;
                        if (dp[i][j] > maxu) {
                                maxu = dp[i][j];
                            }
                    }
                
                }
                dp[i][j] = maxu;
            }
        }       
        cout << dp[p][myv.size()] << endl;
    }
}                                 


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值