日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

转:背包问题的解法

發布時間:2024/9/5 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转:背包问题的解法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背包問題目前有兩種常規解放:遞歸方法和動態規劃法

1.動態規劃方法

轉自:http://blog.sina.com.cn/s/blog_6dcd26b301013810.html

動態規劃的基本思想:

將一個問題分解為子問題遞歸求解,且將中間結果保存以避免重復計算。通常用來求最優解,且最優解的局部也是最優的。求解過程產生多個決策序列,下一步總是依賴上一步的結果,自底向上的求解。

動態規劃算法可分解成從先到后的4個步驟:

1. 描述一個最優解的結構,尋找子問題,對問題進行劃分。

2. 定義狀態。往往將和子問題相關的各個變量的一組取值定義為一個狀態。某個狀態的值就是這個子問題的解(若有k個變量,一般用K維的數組存儲各個狀態下的解,并可根??? 據這個數組記錄打印求解過程。)。

3. 找出狀態轉移方程。一般是從一個狀態到另一個狀態時變量值改變。

4.以“自底向上”的方式計算最優解的值。

5.?從已計算的信息中構建出最優解的路徑。(最優解是問題達到最優值的一組解)

其中步驟1~4是動態規劃求解問題的基礎,如果題目只要求最優解的值,則步驟5可以省略。

背包問題

01背包: 有N件物品和一個重量為M的背包。(每種物品均只有一件)第i件物品的重量是w[i],價值是p[i]。求解將哪些物品裝入背包可使價值總和最大。

完全背包: 有N種物品和一個重量為M的背包,每種物品都有無限件可用。第i種物品的重量是w[i],價值是p[i]。求解將哪些物品裝入背包可使這些物品的費用總和不超過背包重量,且價值總和最大。

多重背包: 有N種物品和一個重量為M的背包。第i種物品最多有n[i]件可用,每件重量是w[i],價值是p[i]。求解將哪些物品裝入背包可使這些物品的費用總和不超過背包重量,且價值總和最大。

01背包問題:

?

這是最基礎的背包問題,特點是:每種物品僅有一件,可以選擇放或不放。

用子問題定義狀態:即c[i][v]表示前i件物品恰放入一個重量為m的背包可以獲得的最大價值。則其狀態轉移方程便是:

c[i][m]=max{c[i-1][m],c[i-1][m-w[i]]+p[i]}

這個方程非常重要,基本上所有跟背包相關的問題的方程都是由它衍生出來的。所以有必要將它詳細解釋一下:“將前i件物品放入重量為m的背包中”這個子問題,若只考慮第i件物品的策略(放或不放),那么就可以轉化為一個只牽扯前i-1件物品的問題。如果不放第i件物品,那么問題就轉化為“前i-1件物品放入容量為v的背包中”,價值為c[i-1][m];如果放第i件物品,那么問題就轉化為“前i-1件物品放入剩下的重量為m-w[i]的背包中”,此時能獲得的最大價值就是c[i-1][m-w[i]]再加上通過放入第i件物品獲得的價值p[i]。

測試數據:
10,3
3,4
4,5
5,6



c[i][j]數組保存了1,2,3號物品依次選擇后的最大價值.

這個最大價值是怎么得來的呢?從背包容量為0開始,1號物品先試,0,1,2,的容量都不能放.所以置0,背包容量為3則里面放4.這樣,這一排背包容量為4,5,6,....10的時候,最佳方案都是放4.假如1號物品放入背包.則再看2號物品.當背包容量為3的時候,最佳方案還是上一排的最價方案c為4.而背包容量為5的時候,則最佳方案為自己的重量5.背包容量為7的時候,很顯然是5加上一個值了。加誰??很顯然是7-4=3的時候.上一排 c3的最佳方案是4.所以。總的最佳方案是5+4為9.這樣.一排一排推下去。最右下放的數據就是最大的價值了。(注意第3排的背包容量為7的時候,最佳方案不是本身的6.而是上一排的9.說明這時候3號物品沒有被選.選的是1,2號物品.所以得9.)

從以上最大價值的構造過程中可以看出。

f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}這就是書本上寫的動態規劃方程.

#include<stdio.h>
int?c[10][100];
int?knapsack(int?m,int?n)
{
????int?i,j,w[10],p[10];
????for(i=1;i<n+1;i++)
????scanf("\n%d,%d",&w[i],&p[i]);
????for(i=0;i<10;i++)
????for(j=0;j<100;j++)
????c[i][j]=0;
????for(i=1;i<n+1;i++)
????for(j=1;j<m+1;j++)
????{
????????if(w[i]<=j){
?????????????if(p[i]+c[i-1][j-w[i]]>c[i-1][j])
?????????????????c[i][j]=p[i]+c[i-1][j-w[i]];?
?????????????else
?????????????????c[i][j]=c[i-1][j];
????????}else?

?????????????c[i][j]=c[i-1][j];
?????}
?????return(c[n][m]);
}
int?main()
{
????int?m,n;int?i,j;

????printf("input the max capacity and the number of the goods:\n");
????scanf("%d,%d",&m,&n);
????printf("Input each one(weight and value):\n");
????printf("%d",knapsack(m,n));
????printf("\n");
????for(i=0;i<10;i++)
????????for(j=0;j<15;j++)
????????{
?????????????printf("%d ",c[i][j]);
?????????????if(j==14)printf("\n");
????????}
????system("pause");
}

遞歸的一個比較直觀的算法

轉自:http://hi.baidu.com/ok558/item/19779ab1922a8fd285dd793f

?

遞歸思想:

?

有N件物品和一個容量為V的背包。第i件物品的體積是c[i],價值是w[i]。求解將哪些物品裝入背包可使價值總和最大。基本思路這是最基礎的背包問題,特點是:每種物品僅有一件,可以選擇放或不放。用子問題定義狀態:即f[i][v]表示前i件物品恰放入一個容量為v的背包可以獲得的最大價值。則其狀態轉移方程便是:

?

?

解釋一下,對于第i件物品來說,最后的結果無非分為?有?第i件商品?和??沒有第i件商品兩種情況,

?

f[i-1][v]也就是有第i件商品的情況,下面的式子自然就是沒有第i件物品取到了最大值。

?

每一種情況也就是取兩者的最大值,來得到最后的結果的,我們很自然就聯想到了遞歸解法。

?

不斷的劃分為子問題來進行求解。

?

?

?

遞歸解法代碼:

?

C++語言:?高亮代碼由發芽網提供

?

#include<iostream>
using?namespace?std;

const?int?W?=?150;
const?int?number?=?5;
const?int?VALUE[]?=?{60,?20,?10,?60,?100};
const?int?WEIGHT[]?=?{20,?30,?50,?60,?80};


//function?Make(?i?{處理到第i件物品}?,?j{剩余的空間為j})?:integer;
int?Make(int?i,?int?j)
{??
int?r1?=?0;
int?r2?=?0;
int?r?=?0;
if?(i?==?-1)
{
return?0;
}

if(j?>=?WEIGHT[i])???//背包剩余空間可以放下物品?i??
{
r1?=?Make(i-1,j?-?WEIGHT[i])?+?VALUE[i];?//第i件物品放入所能得到的價值
r2?=?Make(i-1,j);?//第i件物品不放所能得到的價值??
r?=?(r1>r2)?r1:r2;
}???

return?r;
}


void?main()
{
int?maxValue?=?Make(number-1,?W);
cout<<"maxValue:?"<<maxValue<<endl;
}

?

轉載于:https://www.cnblogs.com/lscheng/p/3286419.html

總結

以上是生活随笔為你收集整理的转:背包问题的解法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。