看了一下0/1背包问题,01背包,说白了就是选和不选的问题。
dp[i][j]代表只考虑前i个物品的情况下,重量为j的背包最优化的选择方法。
所以可以获得递推式子dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - v[i]] + w[i]);
大题意思就是:是否选择拿i物品,使得只考虑前i个物品,重量为j的时候的方案最优。
for(int i = 0 ; i <= C ; i++) dp[0][i] = 0;
for(int i = 1; i <= n ; i++)
for(int j = 0 ; j <= C ; j++){
dp[i][j] = dp[i - 1][j];
if(j - V[i] >= 0)
dp[i][j] = max(dp[i][j],dp[i - 1][j - V[i]
}
一步一步考虑,在所有重量情况下,只选择前i中物品的最优方案。
这样的话其实不考虑打印路径的话,连V,W的值都不需要记录。
for(int i = 0 ; i <= C ; i++) dp[0][i] = 0;
for(int i = 1; i <= n ; i++){
scanf("%d%d",&W,&V);
for(int j = 0 ; j <= C ; j++){
dp[i][j] = dp[i - 1][j];
if(j - V >= 0)
dp[i][j] = max(dp[i][j],dp[i - 1][j - V] + W);
}
}
另外,甚至可以将其变为一维数组。
for(int i = 1; i <= n ; i++){
scanf("%d%d",&W,&V);
for(int j = C ; j >= 0 ; j--){
if(j - V >= 0)
dp[j] = max(dp[j],dp[j - V] + W);
}
}
不过改成一维数组不论是打印路径还是理解都比较困难,就像这道题一样,不推荐使用。
624 | CD | Accepted | C++ | 0.025 |
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<stack>
#include<queue>
#include<set>
#include<ctime>
#include<cmath>
#include<string>
#include<iomanip>
#include<climits>
#include<cctype>
#include<deque>
#include<list>
#include<sstream>
#include<vector>
#include<cstdlib>
using namespace std;
#define _PI acos(-1.0)
#define INF (1 << 30)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pill;
/*================================================
================================================*/
#define MAXD 20 + 10
#define MAX_SIZE 100000 + 10
int V,n;
int CD[MAXD];
int dp[MAXD][MAX_SIZE];
void init(){
scanf("%d",&n);
for(int i = 1 ; i <= n ; i++)
scanf("%d",&CD[i]);
return ;
}
int DP(){
int ans = 0 ;
for(int i = 0 ; i <= n ; i++){
for(int j = 0 ; j <= V ; j++){
dp[i][j] = 0;
if(i)
dp[i][j] = (i == 1 ? 0 : dp[i - 1][j]); /*这句话就是0/1背包的关键*/
if(i && (j - CD[i] >= 0)){
dp[i][j] = max(dp[i][j],dp[i - 1][j - CD[i]] + CD[i]);
}
}
}
return dp[n][V];
}
void print(int VX){ /*打印路径*/
int rote[MAXD];
int size = 0;
for(int i = n - 1; i >= 0 ; i--){
if(dp[i][VX - CD[i + 1]] + CD[i + 1]== dp[i + 1][VX]){
rote[size++] = CD[i + 1];
VX -= CD[i + 1];
}
}
for(int i = size - 1; i >= 0 ; i--)
printf("%d ",rote[i]);
}
int main(){
while(scanf("%d",&V) != EOF){
init();
int ans = DP();
print(ans);
printf("sum:%d\n",ans);
}
return 0;
}