0-1 背包问题

0-1 背包问题:给定 n 种物品和一个容量为 C 的背包,物品 i 的重量是 wi,其价值为 vi 。

问:应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大?

递归解法,对每个物品是否装入背包进行搜索:

int n,w;
int w[maxn],v[maxn];
int rec(int i,int j){
    if(i == n) return 0;
    if(w[i] > j) return rec(i + 1,j);
    else return max(rec(i + 1,j),rec(i + 1,j - w[i]) + v[i]);
}

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

记忆化搜索:

int dp[maxn][maxn];
int rec(int i,int j){
    if(dp[i][j] >= 0) return dp[i][j];
    int res;
    if(i == n) res = 0;
    if(w[i] > j) 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(){
    //memset 只能将数组初始化为 0 或 -1!!!
    memset(dp,-1,sizeof(dp));
    printf("%d\n",rec(0,w));
}

动态规划:

dp[i+1][j] : 从前 i 种物品中选出重量不超过 j 时总价值的最大值。

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

空间优化:

int dp[maxn];
void solve(){
    for(int i = 0;i < n;i++){
        for(int j = W;j >= w[i];j--){
            dp[j] = max(dp[j],dp[j-w[i]] + v[i]);
        }
    }
    printf("%d\n",dp[W]);
}


posted @ 2018-03-18 00:08  ACLJW  阅读(132)  评论(0编辑  收藏  举报