1008 ----- algorithm notes ---------- 0-1 knapsack problem (Dynamic Programming)

Source: Internet
Author: User

1.问题描述

  给定n种物品和一个背包,物品i的重量是wi,其价值为vi,背包的容量为C。问:应该如何选择装入背包的物品,使得装入背包中物品的总价值最大?

2.问题分析

  上述问题可以抽象为一个整数规划问题,即求满足 (a)Σwixi ≤ C;(b)xi ∈(0,1),  1≤i≤n;条件下,∑vixi最大时的一个物品xi序列。分析问题可以发现,该问题具有最优子结构性质,那么就可以尝试用动态规划方法求解,而动态规划求解的关键就是列出问题的递归关系表达式。

  设m(i,j)为背包容量为j,可选物品为i,i+1,...n时0-1背包问题的最优质,那么可有如下递归式:

  m(i,j) = { max( m(i+1, j), m(i+1, j-wi)+vi);   j>=wi;

         { m(i+1, j);               j<wi;

要求的是m(1,c),此时问题就转化为填充m数组的问题了,以n = 5, c = 10, w[] = {2,2,6,5,4},v[] = {6,3,5,4,6},填充的过程如所所示,主要是用上述递归式求值,考虑当前物品能否放入,放入当前物品和不放入导致最终的价值哪个大,图中阴影部分为回溯求xi的过程,表示0,1,4号物品被放入背包中。

i/j 1 2 3 4 5 6 7 8 9 10
4 0 0 0 6 6 6 6 6 6 6
3 0 0 0 6 6 6 6 6 10 10
2 0 0 0 6 6 6 6 6 10 15
1 0 3 3 6 6 9 9 9 9 9
0 0 6 6 9 9 12 12 15 15 15

 

 

 

 

 

 

3.源码

  3.1 非递归

#include <stdio.h>#define N 1024#define max(x, y) (x > y ? x : y)#define min(x, y) (x < y ? x : y)void knapsack(int *w, int *v, int c, int n, int (*m)[N]);void traceback(int *w, int (*m)[N], int *x, int n, int c);int main(int argc, const char *argv[]){    int n, c, w[N], v[N], m[N][N], x[N], i;    scanf("%d%d", &n, &c);    for(i = 0; i < n; i++)        scanf("%d", &w[i]);    for(i = 0; i < n; i++)        scanf("%d", &v[i]);    knapsack(w, v, c, n-1, m);      //这里传的是数组的最大下标    traceback(w, m, x, n-1, c);     //求出是否装载的序列 x[i]    printf("Max v: %d\n", m[0][c]);    for(i = 0; i < n; i++)        printf("x[%d] = %d\t", i, x[i]);    printf("\n");    return 0;}void knapsack(int *w, int *v, int c, int n, int (*m)[N]){    int j, jMax, i;    jMax = min(w[n] - 1, c);    for(j = 0; j <= jMax; j++)      //求m[n][]        m[n][j] = 0;    for(j = c; j > jMax; j--)        m[n][j] = v[n];    for(i = n-1; i > 0; i--){       //依次求m[n-1][] - m[1]        jMax = min(w[i]-1, c);        for(j = 0; j <= jMax; j++){            m[i][j] = m[i+1][j];        }        for(j = c; j > jMax; j--){            m[i][j] = max(m[i+1][j], m[i+1][j-w[i]] + v[i]);        }    }    m[0][c] = m[1][c];              //求m[0][]    if(w[0] < c){        m[0][c] = max(m[1][c], m[1][c-w[0]] + v[0]);    }}void traceback(int *w, int (*m)[N], int *x, int n, int c){    int i;    for(i = 0; i < n-1; i++){        if(m[i][c] == m[i+1][c])    //根据m数组 判断是否装进去            x[i] = 0;        else{            x[i] = 1;            c -= w[i];        }    }    x[n] = (m[n][c] > 0) ? 1 : 0;}

  3.2 递归

#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 5#define C 10int w[] = {2, 2, 6, 5,4};           //使用递归 避免传递太多参数,不清晰int v[] = {6, 3, 5, 4,6};           //因此设置成全局变量int m[N][C], x[N];int knapsack(int i, int j);void traceback();int main(int argc, const char *argv[]){    int i;    knapsack(0, C);    traceback();    printf("Max :%d\n", m[0][10]);    for(i = 0; i < N; i++)        printf("x[%d] = %d\t", i, x[i]);    printf("\n");    return 0;}int knapsack(int i, int j){    if(i == N-1){        m[i][j] = (j > w[i] ? v[i] : 0);        return  m[i][j];    }    int ret1, ret2;    if(j < w[i]){        m[i][j] = knapsack(i+1, j);    }    else{        ret1 = knapsack(i+1, j);        ret2 = knapsack(i+1, j-w[i]) + v[i];        m[i][j] =  ret1 > ret2 ? ret1 : ret2;    }    return m[i][j];}void traceback(){    int i, n = N-1, c = C;    for(i = 0; i < n; i++){        if(m[i][c] == m[i+1][c])    //根据m数组 判断是否装进去            x[i] = 0;        else{            x[i] = 1;            c -= w[i];        }    }    x[n] = (m[n][c] > 0) ? 1 : 0;}

  3.3 书上有种改进的算法,采用跳跃点实现,暂时还没看懂,也许过两天在看就懂了呢。

 

1008-----算法笔记----------0-1背包问题(动态规划求解)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.