动态规划:01背包问题(使用递归方法)
// 最優(yōu)原則:不管前面的策略如何,此后的決策是是基于當(dāng)前狀態(tài)(由上一次決策產(chǎn)生)的最優(yōu)決策。
// 當(dāng)最優(yōu)決策序列中包含最優(yōu)決策子序列時,可建立動態(tài)規(guī)劃遞歸方法。
//
(有些問題的遞歸式不一定能保證最優(yōu)原則,因此在求解時有必要對它進(jìn)行驗證。若不能保持最優(yōu)原則,則不可應(yīng)用動態(tài)規(guī)劃方法。)
//
在得到最優(yōu)解的遞歸式之后,需要執(zhí)行回溯以構(gòu)造最優(yōu)解。
// 缺點:如果不努力地去避免重復(fù)計算,遞歸程序的復(fù)雜性將非常可觀。
//
方案:如果在遞歸程序中解決了重復(fù)計算問題時,復(fù)雜性將急劇下降。
//
遞歸方程也可用迭代方程來求解,這很自然地避免了重復(fù)計算。迭代方程雖然具有相同的復(fù)雜性,不需要附加的遞歸棧空間,因此更快一些。
// 15x1.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <iostream.h>
#include <stdlib.h>
#include "dosmax.h" // has max() and min()
// 動態(tài)規(guī)劃:0-1背包問題(使用遞歸方法)
int p[6] = {0, 6, 3, 5, 4, 6}; // p 價值,多放置一個0,是為了讓下標(biāo)統(tǒng)一,方便理解和計算。
int w[6] = {0, 2, 2, 6, 5, 4}; // w 重量
// int x[6];
int n = 5; // 所有物品的數(shù)量
int c = 10; // 實際最大總?cè)萘?/p>
// F函數(shù)的返回值是,當(dāng)前剩為余容量為y,并且當(dāng)前仍有剩余物品從i到n時,的最優(yōu)解。
// i為當(dāng)前檢索到哪個物品的序號
int F(int i, int y)
{
if (i == n) return (y < w[n]) ? 0 : p[n]; // 最終返回點,一次性比較搞定!
if (y < w[i]) return F(i+1, y); //
如果y小于當(dāng)前重量,那么只有一個選擇:繼續(xù)向下搜尋,看看能不能放下后面的物品
//
如果y大于當(dāng)前物品的重量w[i],就有兩個選擇了(雖然不能當(dāng)場計算出這兩個選擇的值,但是沒關(guān)系,讓它們繼續(xù)往下計算就是了):
// 最后返回(假設(shè)當(dāng)前不放入物品,y的值不變)和(假設(shè)當(dāng)前放入物品,y減去當(dāng)前物品的重量)的兩種不同選擇之后,所造成不同價值的比較結(jié)果。
// 在i=n之前,所有的F函數(shù)代表的臨時總價值,都是懸而未決的。但是一旦i=n之后,依次返回正確的值。
// F(i+1,y) 和 F(i+1,
y-w[i])+p[i],它們都是i+1時候的情況,分頭進(jìn)行計算,相互不依賴。層次分解,就好象是一顆二叉樹(中間如果y<w[i]就只有一個節(jié)點)。
// 最后只得出一個F的值(最優(yōu)值),其余F的臨時總價值,全部丟棄。
return max(F(i+1,y), F(i+1, y-w[i])+p[i]); // 切記,返回的是物品的總價值(最大值=最優(yōu)解)
}
void main(void)
{
cout << "Optimal value is ";
cout << F(1, c) << endl;
}
// =============================dosmax.h=====================================================
#ifndef dosmax_
#define dosmax_
template <class type>
inline type max(type a, type b)
{
return (a > b)? a : b;
}
template <class type>
inline type min(type a, type b)
{
return (a < b)? a : b;
}
#endif
// ==================================================================================
// 如果下標(biāo)從0開始,那么只需要改碰到n的情況,因為沒有w[n]和p[n]存在。但當(dāng)前w[i]與p[i]不變。
int p[5] = {6, 3, 5, 4, 6}; // p 價值,多放置一個0,是為了讓下標(biāo)統(tǒng)一,方便理解和計算。
int w[5] = {2, 2, 6, 5, 4}; // w 重量
int n = 5; // 所有物品的數(shù)量
int c = 10; // 實際最大總?cè)萘?/p>
int F(int i, int y)
{
if (i == n-1) return (y < w[n-1]) ? 0 : p[n-1]; // cas d'arret,一次性比較搞定!
if (y < w[i]) return F(i+1, y);
return max(F(i+1,y), F(i+1, y-w[i])+p[i]);
}
void main(void)
{
cout << "Optimal value is ";
cout << F(0, c) << endl;
}
總結(jié)
以上是生活随笔為你收集整理的动态规划:01背包问题(使用递归方法)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。