题意:
给出几组背包,每组背包都有一种对应的类型,(取至少一个,取最多有个,任意取),每个物品只能取一次,计算满足条件的最大价值。
分析:
只要是提醒自己记住三种背包的写法,其实也挺好理解的,
注意的是至少取一个两个判断条件不能互换,因为可能存在0的情况,所以互换可能导致一个物品取了两次。
最多取一次不能写成因为可能之前那个物品已经算出来了dp[x][v]的最大值,而在下一次算的时候没有考虑。
自由取的时候,我刚开始是从最少取一个加上跟不取比较最大值,但是一直WA,仔细想了下原因在与没有及时更新当前组,导致可能有些解更新不上,所以将其放在最外面更新,就AC了。还有一种是在最多取的基础上进行修改,当然这个就好理解了。
下面给出自由取的两种实现方式。
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int n,T,m;
struct node{
int c,g;
node(int c,int g):c(c),g(g){}
node(){}
};
vector<node> p[maxn];
int s[maxn];
int dp[maxn][maxn];
void least(int x){
for(int i=0;i<p[x].size();i++){
for(int v=T;v>=p[x][i].c;v--){
if(dp[x][v-p[x][i].c]!=-1){
dp[x][v]=max(dp[x][v],dp[x][v-p[x][i].c]+p[x][i].g);
}
if(dp[x-1][v-p[x][i].c]!=-1){
dp[x][v]=max(dp[x][v],dp[x-1][v-p[x][i].c]+p[x][i].g);
}
}
}
}
void most(int x){
for(int i=0;i<=T;i++){
dp[x][i]=dp[x-1][i];
}
for(int i=0;i<p[x].size();i++){
for(int v=T;v>=p[x][i].c;v--){
if(dp[x-1][v-p[x][i].c]!=-1)
dp[x][v]=max(dp[x][v],dp[x-1][v-p[x][i].c]+p[x][i].g);
}
}
}
void free(int x){
for(int i=0;i<=T;i++){
dp[x][i]=dp[x-1][i];
}
for(int i=0;i<p[x].size();i++){
for(int v=T;v>=p[x][i].c;v--){
if(dp[x][v-p[x][i].c]!=-1){
dp[x][v]=max(dp[x][v],dp[x][v-p[x][i].c]+p[x][i].g);
}
if(dp[x-1][v-p[x][i].c]!=-1){
dp[x][v]=max(dp[x][v],dp[x-1][v-p[x][i].c]+p[x][i].g);
}
}
}
}
int main(){
while(scanf("%d%d",&n,&T)!=EOF){
for(int i=1;i<=n;i++){
p[i].clear();
}
for(int i=1;i<=n;i++){
scanf("%d%d",&m,&s[i]);
for(int j=1;j<=m;j++){
int c,g;
scanf("%d%d",&c,&g);
p[i].push_back(node(c,g));
}
}
memset(dp,-1,sizeof dp);
for(int i=0;i<=T;i++){
dp[0][i]=0;
}
for(int i=1;i<=n;i++){
if(s[i]==0){
least(i);
}else if(s[i]==1){
most(i);
}else free(i);
}
printf("%d\n",dp[n][T]);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int n,T,m;
struct node{
int c,g;
node(int c,int g):c(c),g(g){}
node(){}
};
vector<node> p[maxn];
int s[maxn];
int dp[maxn][maxn];
void least(int x){
for(int i=0;i<p[x].size();i++){
for(int v=T;v>=p[x][i].c;v--){
if(dp[x][v-p[x][i].c]!=-1){
dp[x][v]=max(dp[x][v],dp[x][v-p[x][i].c]+p[x][i].g);
}
if(dp[x-1][v-p[x][i].c]!=-1){
dp[x][v]=max(dp[x][v],dp[x-1][v-p[x][i].c]+p[x][i].g);
}
}
}
}
void most(int x){
for(int i=0;i<=T;i++){
dp[x][i]=dp[x-1][i];
}
for(int i=0;i<p[x].size();i++){
for(int v=T;v>=p[x][i].c;v--){
if(dp[x-1][v-p[x][i].c]!=-1)
dp[x][v]=max(dp[x][v],dp[x-1][v-p[x][i].c]+p[x][i].g);
}
}
}
void free(int x){
for(int i=0;i<=T;i++){
dp[x][i]=dp[x-1][i];
}
for(int i=0;i<p[x].size();i++){
for(int v=T;v>=p[x][i].c;v--){
if(dp[x][v-p[x][i].c]!=-1)
dp[x][v]=max(dp[x][v],dp[x][v-p[x][i].c]+p[x][i].g);
}
}
}
int main(){
while(scanf("%d%d",&n,&T)!=EOF){
for(int i=1;i<=n;i++){
p[i].clear();
}
for(int i=1;i<=n;i++){
scanf("%d%d",&m,&s[i]);
for(int j=1;j<=m;j++){
int c,g;
scanf("%d%d",&c,&g);
p[i].push_back(node(c,g));
}
}
memset(dp,-1,sizeof dp);
for(int i=0;i<=T;i++){
dp[0][i]=0;
}
for(int i=1;i<=n;i++){
if(s[i]==0){
least(i);
}else if(s[i]==1){
most(i);
}else free(i);
}
printf("%d\n",dp[n][T]);
}
return 0;
}