第一道题:https://www.luogu.org/problemnew/show/P1060
这道题就是一道非常的01背包模板,不过需要注意到题目的条件还需要乘上重要性,也就是价值=原价值*重要度,其他的就按照01背包模板照打即可。
附上代码吧:
#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+20;
int a[maxn],w[maxn],v[maxn],f[maxn];
int main(){
int n,m,k;
cin>>m>>n;
for(int i=1;i<=n;i++){
cin>>v[i]>>k;
w[i]=k*v[i];
}
for(int i=1;i<=n;i++)
for(int j=m;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+w[i]);
cout<<f[m];
return 0;
}
第二道题:https://www.luogu.org/problemnew/show/P1064
这一道题比上一道题难度明显增加了许多,而且,这道题的背包有依赖性了,也就是以来背包,思路:
价值=原价值*重要度不变,但后面多了个附件的条件,也就是说,每一个主件都最多可以拥有2个附件,则输入时需要优先存储每一个附件的归属情况,这里我用二位数组存储,那么,读入的代码就是这样的:
//q1是第一个附件的存储情况,q2是第二个附件的存储情况,v是价值,p是重要度,q是是否为附件,若是,又为谁的附件。
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>v[i]>>p[i]>>q[i];
if(!q[i]){
w[i]=v[i];
c[i]=v[i]*p[i];
}
else{
q1[q[i]][0]++;
q1[q[i]][q1[q[i]][0]]=v[i];
q2[q[i]][q1[q[i]][0]]=v[i]*p[i];
}
}
接下来,在DP的循环里面,我们也需要考虑几种情况:
1.若是第一个附件
2.若是第二个附件
3.如果即是第一个附件又是第二个附件
所以,附上重要部分的代码:
for(int i=1;i<=m;i++)
for(int j=n;j>=w[i];j--){
f[j]=max(f[j],f[j-w[i]]+c[i]);
if(j-w[i]-q1[i][1]>=0)
f[j]=max(f[j],f[j-w[i]-q1[i][1]]+c[i]+q2[i][1]);
if(j-w[i]-q1[i][2]>=0)
f[j]=max(f[j],f[j-w[i]-q1[i][2]]+c[i]+q2[i][2]);
if(j-w[i]-q1[i][1]-q1[i][2]>=0)
f[j]=max(f[j],f[j-w[i]-q1[i][1]-q1[i][2]]+c[i]+q2[i][1]+q2[i][2]);
}
最后,附上完整代码:
#include <iostream>
const int maxn=1000+50;
using namespace std;
int n,m,f[maxn],v[maxn],p[maxn],q[maxn],w[maxn],c[maxn],q1[maxn][maxn],q2[maxn][maxn];
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>v[i]>>p[i]>>q[i];
if(!q[i]){
w[i]=v[i];
c[i]=v[i]*p[i];
}
else{
q1[q[i]][0]++;
q1[q[i]][q1[q[i]][0]]=v[i];
q2[q[i]][q1[q[i]][0]]=v[i]*p[i];
}
}
for(int i=1;i<=m;i++)
for(int j=n;j>=w[i];j--){
f[j]=max(f[j],f[j-w[i]]+c[i]);
if(j-w[i]-q1[i][1]>=0)
f[j]=max(f[j],f[j-w[i]-q1[i][1]]+c[i]+q2[i][1]);
if(j-w[i]-q1[i][2]>=0)
f[j]=max(f[j],f[j-w[i]-q1[i][2]]+c[i]+q2[i][2]);
if(j-w[i]-q1[i][1]-q1[i][2]>=0)
f[j]=max(f[j],f[j-w[i]-q1[i][1]-q1[i][2]]+c[i]+q2[i][1]+q2[i][2]);
}
cout<<f[n];
return 0;
}