一拿到这题的时候,一时脑阻塞了,虽然知道肯定是01背包,但是却不知道怎么变形。
后来看了网上的代码,才恍然大悟,原来只需将01背包优化过程中的前K种情况储存起来就可以了。
01背包的状态转移方程为:dp[i][v]=max(dp[i-1][v],dp[i-1][v-vi[i]]+va[i]);而要储存起前K种情况就需要将状态方程转化为:dp[i-1][v]=>dp[i-1][v][1……k],dp[i-1][v-vi[i]]+va[i]=>dp[i-1][v-vi[i]][1……k]+va[i];
这样就可以解决该问题了。
这是AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int vi[105],va[105],dp[1005][35],a[35],b[35];
int main(void)
{
int t;
cin>>t;
while(t--){
int n,v,k;
cin>>n>>v>>k;
for(int i=0;i<n;i++)
cin>>va[i];
for(int i=0;i<n;i++)
cin>>vi[i];
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++){
for(int vo=v;vo>=vi[i];vo--){
for(int kk=1;kk<=k;kk++){
a[kk]=dp[vo-vi[i]][kk]+va[i];
b[kk]=dp[vo][kk];
}
b[k+1]=a[k+1]=-1;
int aa,bb,c;
aa=bb=c=1;
while(c<=k&&(a[aa]!=-1||b[bb]!=-1)){
if(a[aa]>b[bb])
dp[vo][c]=a[aa],aa++;
else
dp[vo][c]=b[bb],bb++;
if(dp[vo][c]!=dp[vo][c-1])
c++;
}
}
}
cout<<dp[v][k]<<endl;
}
}