背包问题(一个以及无限个)

题目说明:

假設有一個背包的負重最多可達8公斤,而希望在背包中裝入負重範圍內可得之總價物品,假設是水果好了,水果的編號、單價與重量如下所示

 

0 李子 4KG NT$4500
1 蘋果 5KG NT$5700
2 橘子 2KG NT$2250
3 草莓 1KG NT$1100
4 甜瓜 6KG NT$6700

 

首先,是每种水果都只有一个的算法。

#include <stdio.h>
#include <stdlib.h>

int getMax(int fruitP[], int fruitW[], int form[][9], int fruitNum, int bagW){
    int i, j;

    for(i = 1; i <= fruitNum; i++){
        for(j = 1; j <= bagW; j++){
            if(j - fruitW[i] < 0){
                form[i][j] = form[i - 1][j];
            }else if(form[i - 1][j - fruitW[i]] + fruitP[i] > form[i - 1][j]){
                form[i][j] = form[i - 1][j - fruitW[i]] + fruitP[i];
            }else{
                form[i][j] = form[i - 1][j];
            }
        }
    }
}

print(int form[][9], int h, int l){
    int i, j;
    for(i = 0; i < l; i++) printf("%.5d  ", i);
    printf("\n");
    for(i = 0; i < h; i++){
        for(j = 0; j < l; j++){
            printf("%.5d  ", form[i][j]);
        }
        printf("\n");
    }
}


main(){
    int fruitP[6] = {0, 450, 570, 225, 110, 670};
    int fruitW[6] = {0, 4, 5, 2, 1, 6};
    int form[6][9] = {0};
    getMax(fruitP, fruitW, form, 5, 8);
    print(form, 6, 9);
}

 

如果水果是无限个则可以这么写:

#include <stdio.h>
#include <stdlib.h>

int getMax(int fruitP[], int fruitW[], int form[][9], int fruitNum, int bagW){
    int i, j;

    for(i = 1; i <= fruitNum; i++){
        for(j = 1; j <= bagW; j++){
            if(j - fruitW[i] < 0){
                form[i][j] = form[i - 1][j];
            }else if(form[i - 1][j - fruitW[i]] + fruitP[i] > form[i - 1][j]){
                if(form[i - 1][j - fruitW[i]] + fruitP[i] > form[i][j - fruitW[i]] + fruitP[i])
                    form[i][j] = form[i - 1][j - fruitW[i]] + fruitP[i];
                else form[i][j] = form[i][j - fruitW[i]] + fruitP[i];
            }else{
                if(form[i][j - fruitW[i]] + fruitP[i] < form[i - 1][j])
                    form[i][j] = form[i - 1][j];
                else form[i][j] = form[i][j - fruitW[i]] + fruitP[i];
            }
        }
    }
}

print(int form[][9], int h, int l){
    int i, j;
    for(i = 0; i < l; i++) printf("%.5d  ", i);
    printf("\n");
    for(i = 0; i < h; i++){
        for(j = 0; j < l; j++){
            printf("%.5d  ", form[i][j]);
        }
        printf("\n");
    }
}


main(){
    int fruitP[6] = {0, 450, 570, 225, 110, 670};
    int fruitW[6] = {0, 4, 5, 2, 1, 6};
    int form[6][9] = {0};
    getMax(fruitP, fruitW, form, 5, 8);
    print(form, 6, 9);
}

 

一个和无限个的差别在于,在作比较的时候不仅跟上一行比较,还要跟当前行作比较,较大者置换即可。

过程之中的主要问题是一个初始化的问题,之所以5*8个元素需要用到6*9个空间,最主要还是为了理解上以及编写上的方便。

其实有类似的更好的算法,空间上只需一维数组,而且也没不管水果的个数是一个还是无限,只需要在遍历数组的时候改一下方向即可,但是本题作为动态规划入门练习,可能以上面的方法为主会比较好。

动态规划的问题之一是需要大量的空间,所以其实更好的算法的根本目的就是压缩空间。

posted @ 2014-03-06 13:47  yutoulck  阅读(917)  评论(0编辑  收藏  举报