算法:动态规划解 0-1 背包问题

本文深入探讨动态规划方法及其在解决0-1背包问题中的应用,通过递推与递归两种实现方式,详细阐述了解题过程及关键逻辑,旨在提供一种高效求解组合优化问题的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


动态规划是用来解决“最优”问题,通过找到最优的子策略来解决这个问题


解决方法

    递归:从结果出发,指导终止条件

    递推:按顺序进行,但可以保存阶段状态


与分治法的区别:


(分治法的步骤:

   分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;

    解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题

    合并:将各个子问题的解合并为原问题的解。

    例子:汉诺塔

在递归过程中,动态规划就是分治法中多了了比较


例子:


0-1背包问题的实现


=============================== 递推 ===================================

#define OBJ_COUNT 4

#define TOTAL_WEIGHT 4


int main() {

    cout << " 0,1 bage" << endl; // prints !!!Hello World!!!


    // 1st dimension,  obj index

    // 2nd dimension, 1:weight; 2: value

    int objs[OBJ_COUNT][2] = { {1,2}, {2,4} , {3,6}, {1,3} ,};


    int v[OBJ_COUNT][TOTAL_WEIGHT+1];


    for(int i=0; i < OBJ_COUNT; i++)

        for (int j=1; j<= TOTAL_WEIGHT; j++ )

            v[i][j] = 0;


    v[0][objs[0][0]] = objs[0][1]; // input the 1st obj


    for ( int i=1; i < OBJ_COUNT; i++) {

        for( int j=1; j<= TOTAL_WEIGHT; j++ ) {

            //cout << "objs[i][0]:" << objs[i][0] << " j:" << j <<endl;

            if ( objs[i][0] > j)

                v[i][j] = v[i-1][j];  //no update, because weight too large

            else if ( objs[i][0] == j)

                v[i][j] = v[i-1][j] < objs[i][1]? objs[i][1]: v[i-1][j];  // 看同权值的总重为 j 的是否权值较小, 取最大权值

            else {  

                int correspondIndex = j - objs[i][0]; //取去掉当前 obj 的总量,

                int newWeight = v[i-1][correspondIndex] + objs[i][1];  // 重新计算

                if ( newWeight >  v[i-1][j])  //取最大权值

                    v[i][j] = newWeight;

            }

        }

    }


    cout << "w: ";

    for (int j=1; j<= TOTAL_WEIGHT; j++ )

        cout << j << "  ";

    cout << endl;


    for ( int i=0; i < OBJ_COUNT; i++){

        cout << i<<": ";

        for (int j=1; j<= TOTAL_WEIGHT; j++ )

            cout << v[i][j] << "  ";

        cout << endl;

    }


    return 0;

}


=============================== 递归 ===================================


#define OBJ_COUNT 4

#define TOTAL_WEIGHT 4

int objs[OBJ_COUNT+1][2] = { {0,0}, {1,2}, {2,4} , {3,6}, {1,3} ,};

int F(int n, int v) {

    if ( n==0 )

        return 0;

    else {

        if ( objs[n][0] > v ) {

            return F( n-1, v);

        }

        else  {

            int a = F( n-1, v);

            int b = F( n-1, v-objs[n][0] ) + objs[n][1];

            return a>b? a: b;

        }

    }

}

int main() {

    cout << " 0,1 bage" << endl;

    cout << F(OBJ_COUNT,TOTAL_WEIGHT);

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值