背包问题的变化
求第k优解
我们曾经所见的背包都是求第一优解,但对于求解第K优解也很容易
其实在求解第一优解的时候,本质就是进行两个有序序列
f
[
i
]
[
j
]
,
f
[
i
−
1
]
[
j
−
w
[
i
]
]
+
v
[
i
]
f[i][j],f[i-1][j-w[i]]+v[i]
f[i][j],f[i−1][j−w[i]]+v[i]的合并,那么我们只需要将两个序列都存储起来,在最后进行合并即可
T1 HDU2639
题解
求第K优解的板子
代码
#include<bits/stdc++.h>
#define M 1009
using namespace std;
int read(){
int f=1,re=0;
char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-'){f=-1,ch=getchar();}
for(;isdigit(ch);ch=getchar()) re=(re<<3)+(re<<1)+ch-'0';
return re*f;
}
int w[M],v[M],f[M][M],a[M],b[M],tot1,tot2,tot3,n,m,k,t;
int main(){
t=read();
while(t--){
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++) v[i]=read();
for(int i=1;i<=n;i++) w[i]=read();
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
for(int j=m;j>=w[i];j--){
for(int e=1;e<=k;e++)
a[e]=f[j][e],b[e]=f[j-w[i]][e]+v[i];
a[k+1]=b[k+1]=-1;//这步很关键
tot1=tot2=tot3=1;
//for(int e=1;e<=k;e++) printf("%d %d\n",a[e],b[e]);
while(tot1!=k+1&&(a[tot2]!=-1||b[tot3]!=-1)){
if(a[tot2]>b[tot3]) f[j][tot1]=a[tot2],tot2++;
else f[j][tot1]=b[tot3],tot3++;
if(f[j][tot1]!=f[j][tot1-1]) tot1++;
}
}printf("%d\n",f[m][k]);
}return 0;
}