【分组背包】HDU 1712 ACboy needs your help

 HDU 1712 ACboy needs your help

题意:N门课程,有M天时间。【每门课程花费1-M天可以获得的价值不同】,问怎么选择花费在每一门上的课程能获得最大价值,输出最大价值。

 

思路:分组背包模板题

每一门课程的时间选择都是冲突的,只能选择一个。那么每一门课程就是一个组别,并且天数的选择是冲突的,只能选择一个。就典型的分组背包问题。

第一层循环是枚举每一个组别 k ;第二层循环是背包容量的枚举,j 从V->0;第三层循环是枚举第k个组别的每个物品,如果在j可容纳范围内,就更新当前dp[j]的值为最大{选择该物品,或不选择该物品},就变成是一个01背包问题。

 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <limits>
#include <set>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f
#define MID (l + r) >> 1
#define lsn rt << 1
#define rsn rt << 1 | 1
#define Lson lsn, l, mid
#define Rson rsn, mid + 1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr

#define lowbit(x) x & (-x)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 100 + 5;

int N, M;
struct node{
    int val, cost;
    node(int a = 0, int b = 0): val(a), cost(b) {}
    friend bool operator < (node n1, node n2) { return n1.val > n2.val; }
};
int dp[maxN];
vector<node>vt[maxN];
void init()
{
    for(int i = 0; i <= N; i ++ )
        vt[i].clear();
    for(int i = 0; i <= M; i ++ )
        dp[i] = 0;
}
int main()
{
    while(~scanf("%d%d", &N, &M) && (N || M))
    {
        init();
        for(int i = 1; i <= N; i ++ )
        {
            for(int j = 1; j <= M; j ++ )
            {
                int val; scanf("%d", &val);
                vt[i].push_back(node(val, j));//花费j得到val的价值
            }
        }
        for(int k = 1; k <= N ; k ++ )//枚举组
            for(int j = M; j >= 0; j -- )//背包容量
            {
                int siz = vt[k].size();
                for(int i = 0; i < siz; i ++ )//属于第k组的物品标号
                {
                    if(j >= vt[k][i].cost)
                        dp[j] = max(dp[j], dp[j - vt[k][i].cost] + vt[k][i].val);
                }
            }
        printf("%d\n", dp[M]);
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值