hdu1712 分组背包

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1712

题意:有n门课程,和m天时间,完成mp[i][j]得到的价值为第i行j列的数字,求最大价值。

思路:分组背包。

分组背包:

问题

有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

算法

这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值,则有:

f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于第k组}

使用一维数组的伪代码如下:

for 所有的组k

    for v=V..0

        for 所有的i属于组k

            f[v]=max{f[v],f[v-c[i]]+w[i]}

注意这里的三层循环的顺序,“for v=V..0”这一层循环必须在“for 所有的i属于组k”之外。这样才能保证每一组内的物品最多只有一个会被添加到背包中。

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

int mp[105][105];
int dp[105];

int N,M;

int main()
{
    while(cin>>N>>M && (N+M))
    {
        for(int i=1; i<=N; i++)
            for(int j=1; j<=M; j++)
                cin>>mp[i][j];
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=N; i++)
            for(int j=M; j>=0; j--)
                for(int k=1; k<=M; k++)
                    if(j>=k) dp[j]=max(dp[j],dp[j-k]+mp[i][k]);
        cout<<dp[M]<<endl;
    }
    return 0;
}

 

posted @ 2016-10-13 17:02  a_clown_cz  阅读(104)  评论(0)    收藏  举报