【动态规划】之01背包问题(难度:2星)

来源:互联网 发布:最新网络红歌有哪些 编辑:程序博客网 时间:2024/05/23 19:44

#include <stdio.h>/** * 原题: * 一个贼在偷窃一家商店时发现了N件物品,其中第i件值v[i]元,重w[i]磅。 * 他希望偷走的东西总和越值钱越好,但是他的背包只能放下W磅。 * 请求解如何放能偷走最大价值的物品,这里v[i]w[i]W都是整数 */#define MAX(x,y) (x>y?x:y)#define N 5#define W 11static int v[N] = {5,3,4,5,7};static int w[N] = {2,3,4,6,8};/** * 思路如下 * 设子问题为:从第i件物品开始选择,当前背包剩余可容量为j,求出在此条件下所能获得的最大价值max_v * 找出边界:显然i=N,max_v=0(i=N,说明已经没有物品可选了), j=0,max_v=0(可容量为0,自然没有物品可选,价值自然为0) *///解法1:递归int solve_1(int i, int j){    if (j == 0 || i == N)        return 0;    //容量不够时, 只能选择尝试下一件物品    if (w[i] > j)        return solve_1(i+1, j);    //容量足够时, 在选择当前物品和尝试下一件物品之中选择价值最高的    return MAX(solve_1(i+1,j-w[i]) + v[i], solve_1(i+1, j));}//解法2:递归+记忆数组的dpstatic int memo[N+1][W+1];int solve_2(int i, int j){    if (j == 0 || i == N)        return memo[i][j] = 0;    if (memo[i][j] > -1)        return memo[i][j];    //容量不够时, 只能选择尝试下一件物品    if (w[i] > j)        return memo[i][j] = solve_2(i+1, j);    //容量足够时, 在选择当前物品和尝试下一件物品之中选择价值最高的    return memo[i][j] = MAX(solve_2(i+1,j-w[i]) + v[i], solve_2(i+1, j));}//解法3:递推形static int max_v[N+1][W+1];int solve_3(){    for (int i = N-1; i >= 0; --i) {        for (int j = 1; j <= W; ++j) {            if (w[i] > j)                max_v[i][j] = max_v[i+1][j];            else                max_v[i][j] = MAX(max_v[i+1][j-w[i]]+v[i], max_v[i+1][j]);        }    }    return max_v[0][W];}int main() {    printf("solve_1:%d\n", solve_1(0, W));    for (int i = 0; i <= N; ++i) {        for (int j = 0; j <= W; ++j) {            memo[i][j] = -1;        }    }    printf("solve_2:%d\n", solve_2(0, W));//    for (int i = 0; i <= N; ++i) {//        for (int j = 0; j <= W; ++j) {//            printf("%d\t", memo[i][j]);//        }//        printf("\n");//    }    printf("solve_3:%d\n", solve_3());//    for (int i = 0; i <= N; ++i) {//        for (int j = 0; j <= W; ++j) {//            printf("%d\t", max_v[i][j]);//        }//        printf("\n");//    }    return 0;}

运行结果:

solve_1:13solve_2:13solve_3:13



原创粉丝点击