主要是要找到状态转移方程。
第一种办法,开dp[N][V],表示前N个物品,占体积V的最优价值。
在这种方法的情况下,dp[i][j]由两个状态的最优值转移过来,分别是拿了没拿第i个(dp[i-1][j]),和拿了第i个(dp[i-1][j-ti[i]]+jia[i])这两种状态。
代码为
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define INF 0x6FFFFFFF
#define NINF -(1<<30)
#define mxn 1005
using namespace std;
//int dp[mxn][mxn],ti[mxn],jia[mxn];
int d[mxn],ti[mxn],jia[mxn];
int n,V;
int main(void){
int t;
scanf("%d",&t);
while(t--){
cin>>n>>V;
for(int i=1;i<=n;i++){
scanf("%d",&jia[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&ti[i]);
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
for(int j=0;j<=V;j++){
if(j-ti[i]>=0){
dp[i][j]=max(dp[i-1][j],dp[i-1][j-ti[i]]+jia[i]);
}
else{
dp[i][j]=dp[i-1][j];
}
}
}
cout<<dp[n][V]<<endl;
}
return 0;
}
第二种办法,开dp[V],优化了空间,但是时间没有优化(刷表法)
在这种方法的情况下,先假设已知dp数组,然后将每个物品的影响施加到dp数组上,具体表现为
if(j-ti[i]>=0){
d[j]=max(d[j-ti[i]]+jia[i],d[j]);
即对dp数组的每个状态施加影响。
代码为
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define INF 0x6FFFFFFF
#define NINF -(1<<30)
#define mxn 1005
using namespace std;
//int dp[mxn][mxn],ti[mxn],jia[mxn];
int d[mxn],ti[mxn],jia[mxn];
int n,V;
int main(void){
int t;
scanf("%d",&t);
while(t--){
cin>>n>>V;
int mn=INF;
for(int i=0;i<n;i++){
scanf("%d",&jia[i]);
}
for(int i=0;i<n;i++){
scanf("%d",&ti[i]);
mn=min(mn,ti[i]);
}
memset(d,0,sizeof(d));
for(int i=0;i<n;i++){
for(int j=V;j>=0;j--){
if(j-ti[i]>=0){
d[j]=max(d[j-ti[i]]+jia[i],d[j]);
}
}
}
cout<<d[V]<<endl;
// for(int i=0;i<=V;i++){
// printf("i=%d,d[i]=%d\n",i,d[i]);
// }
}
}