金明的预算方案
解题思路
一共有三种可能
一、没有附件
状态转移方程:
dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
就是普通的0-1背包
二、只有一个附件
1.什么都不取
2.取主件
3.取主件和附件
三、有两个附件
1.什么都不取
2.取主件
3.取主件和附件1
4.取主件和附件2
5.取主件,附件1,附件2
代码
#include<iostream>
using namespace std;
int c[100000],p[100000],q[100000],fu[100000],fu1[100000],fu2[100000];
int v[100000];
int main(){
int n,m;
int dp[100000];
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>c[i]>>p[i]>>q[i];
v[i]=c[i]*p[i];
fu[q[i]]++;
if(fu1[q[i]]==0){
fu1[q[i]]=i;
}else{
fu2[q[i]]=i;
}
}
for(int i=1;i<=m;i++){
for(int j=n;j>=0;j--){
if(q[i]==0){
if(j>=c[i]){
if(fu[i]==0){
dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
}else if(fu[i]==1){
dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
if(j>=c[i]+c[fu1[i]]){
dp[j]=max(dp[j],dp[j-c[i]-c[fu1[i]]]+v[i]+v[fu1[i]]);
}
}else if(fu[i]==2){
dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
if(j>=c[i]+c[fu1[i]]){
dp[j]=max(dp[j],dp[j-c[i]-c[fu1[i]]]+v[i]+v[fu1[i]]);
}
if(j>=c[i]+c[fu2[i]]){
dp[j]=max(dp[j],dp[j-c[i]-c[fu2[i]]]+v[i]+v[fu2[i]]);
}
if(j>=c[i]+c[fu1[i]]+c[fu2[i]]){
dp[j]=max(dp[j],dp[j-c[i]-c[fu1[i]]-c[fu2[i]]]+v[i]+v[fu1[i]]+v[fu2[i]]);
}
//dp[j]=max(dp[j],max(dp[j-c[i]]+v[i],max(dp[j-c[i]-c[fu1[i]]+v[i]+v[fu1[i]]],max(dp[j-c[i]-c[fu2[i]]+v[i]+v[fu2[i]]],dp[j-c[i]-c[fu2[i]]-c[fu1[i]]+v[i]+v[fu1[i]]+v[fu2[i]]]))));
}
}else{
dp[j]=dp[j];
}
}
}
}
/* for(int i=0;i<=n;i++){
cout<<i<<": "<<dp[i]<<endl;
}
cout<<endl;
*/ cout<<dp[n];
return 0;
}