您的位置:首页 > 其它

【DP学习】之 01背包

2017-03-06 17:26 274 查看
参考图书《挑战程序竞赛》

题目 ->



①普通搜索dfs

最容易想到,但数一大,极容易超时。复杂度(o(2^N))

有些被搜索了两次

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX_N 101
int n, W;   //n: 物品数, W: 总重量
int w[MAX_N] = {2, 1, 3, 2};
int v[MAX_N] = {3, 2, 4, 2}; //w:重量,v:价值

int rec(int i, int j){
int res;
if(i == n){
//已经没有剩余物品了
res = 0;
}else if(j < w[i]){
//无法挑选该物品
res = rec(i + 1, j);
}else{
//挑选和不挑选的两种情况都尝试一下
res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
}
return res;
}

void solve(){
printf("%d\n", rec(0, W));
}

int main(void){
n = 4, W = 5;
solve();
return 0;
}


②记忆化数组

即用个数组记录,相当于剪枝了,复杂度(o(nW))

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX_N 101
int n, W;   //n: 物品数, W: 总重量
int w[MAX_N] = {2, 1, 3, 2};
int v[MAX_N] = {3, 2, 4, 2}; //w:重量,v:价值
int dp[MAX_N + 1][MAX_N + 1];   //记忆化数组

int rec(int i, int j){
if(dp[i][j] >= 0){
//已经计算过的话直接使用之前的结果
return dp[i][j];
}
int res;
if(i == n){
res = 0;
}else if(j < w[i]) {
res = rec(i + 1, j);
}else{
res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
}
//将结果记录在数组中
return dp[i][j] = res;
}

void solve(){
printf("%d\n", rec(0, W));
}

int main(void){
//用-1 表示尚未计算过,初始化整个数组
memset(dp, -1, sizeof(dp));
n = 4, W = 5;
solve();
return 0;
}


③DP

一步步按顺序求出问题。复杂度(o(nW))



#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX_N 101
int n, W;   //n: 物品数, W: 总重量
int w[MAX_N] = {2, 1, 3, 2};
int v[MAX_N] = {3, 2, 4, 2}; //w:重量,v:价值
int dp[MAX_N + 1][MAX_N + 1];   //DP数组

void solve(){
for(int i = n - 1; i >= 0; --i) {
for(int j = 0; j <= W; ++j) {
if(j < w[i]){
dp[i][j] = dp[i + 1][j];
}else {
dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);
}
}
}

printf("%d\n", dp[0][W]);
}

int main(void){
//用-1 表示尚未计算过,初始化整个数组
memset(dp, 0, sizeof(dp));
n = 4, W = 5;
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dfs dp 01背包