题意:给一个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; }