hdu 1712 ACboy needs your help(分组背包)

题意:给一个n*m的矩阵,有n种作业,每种作业花费的时间不同获得的价值不同,a[i][j]表示第i种作业花费j天的话收获的价值为a[i][j]。问m天内收获的最大价值。

 

所谓的分组背包就是同个分组里的物品是互斥的,也就是在同一分组里一个物品若选了,则不能再在该分组里选物品了,那么一个分组里的物品要么只选一个,要么一个都不选,那么很显然用01背包的做法就可以写了,只不过对i物品的选择变成了对i分组里的物品选择。

分组的背包问题将彼此互斥的若干物品称为一个组,这建立了一个很好的模型。不少背包问题的变形都可以转化为分组的背包问题(例如P07),由分组的背包问题进一步可定义“泛化物品”的概念,十分有利于解题。

 

//没优化
#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)+1
#define ll long long
#define fuck(x) cout<<#x<<" "<<x<<endl;
const int maxn=1e6+10;
int d[4][2]={1,0,-1,0,0,1,0,-1};
int dp[105][105],mp[105][105];
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF&&n&&m){
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&(mp[i][j]));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
dp[i][j]=dp[i-1][j];//第i个分组里不选物品
for (int k = 1; k <= j; k++)//第i个分组里选物品k
dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + mp[i][k]);
}
cout<<dp[n][m]<<endl;
}
return 0;
}

//优化
#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)+1
#define ll long long
#define fuck(x) cout<<#x<<"     "<<x<<endl;
const int maxn=1e6+10;
int d[4][2]={1,0,-1,0,0,1,0,-1};
int dp[105],mp[105][105];
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF&&n&&m){
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&(mp[i][j]));
        for(int i=1;i<=n;i++)
            for(int j=m;j>=1;j--)
                for(int k=1;k<=j;k++)
                    dp[j]=max(dp[j],dp[j-k]+mp[i][k]);
        cout<<dp[m]<<endl;
    }
    return 0;
}
posted @ 2019-08-14 23:06  eason99  阅读(184)  评论(0编辑  收藏  举报