1. 程式人生 > >0-1揹包問題,用滾動陣列,動態規劃解決

0-1揹包問題,用滾動陣列,動態規劃解決

接觸了很多的0-1揹包的問題,這個問題是動態規劃的經典題,總結一下,加深自己的印象,也

為大家做個參考,對blog有問題可以直接評論,我會盡快的回答!

題目:有N件物品和一個容量為V的揹包,第i件物品的體積w[i],價值是c[i],求解將那些物品裝入揹包

可使這些物品的費用總和不超過揹包容量,且使揹包內的物品價值總和最大!

F[i][w]----對於前i物品而言,使體積為w的揹包內物品價值總和最大,最大的價值為F[i][w].

下面這個方程為整個揹包問題的核心:

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

對於第i件物品,你可以選擇把它裝入揹包,還可以選擇前i-1件物品對於體積為w的揹包的最優解,

選擇其中的最大值,就是F[i][w]的值了!

話不多說,直接上程式碼,更加清楚得了解!

程式碼1

#include<iostream> 
using namespace std;

int F[100][100]; //定義一個二維陣列
int w[100]; //體積陣列
int c[100];  //價值陣列
int n;   //物品總數
int V;  //揹包的體積 

int max(int a,int b);

int main() 
 {
 	
 	while(cin>>n&&cin>>V)
 	{
 	 int i,j; 
 	 
 	 for(i=1;i<=n;i++)//初始化資料 
 	   cin>>w[i]>>c[i];  
     
	 for(i=1;i<=n;i++)		
	  for(j=1;j<=V;j++)
	   if(j>w[i]) 
	  F[i][j]=max(F[i-1][j],F[i-1][j-w[i]]+c[i]);
	  else F[i][j]=F[i-1][j];
 	  cout<<F[n][V];
 	}
 }
int max(int x,int y)
 {
 	
 	return x>y?x:y;
 }
這個程式碼是,對於二維陣列而言,一旦物品數和重量多了起來,程式的複雜度就很大,所以

必須減少時間複雜度,可以從優化空間的角度來看這個問題!

可以用一個滾動陣列來代替二維陣列,讓陣列動起來

如果你認真看了程式碼1,程式碼2就比較簡單的理解!

程式碼2:

#include<iostream> 
using namespace std;

int F[100]; //定義一個一維陣列
int w[100]; //體積陣列
int c[100];  //價值陣列
int n;   //物品總數
int V;  //揹包的體積 

int max(int a,int b);

int main() 
 {
 	
 	while(cin>>n&&cin>>V)
 	{
 	 int i,j; 
 	 
 	 for(i=1;i<=n;i++)//初始化資料 
 	   cin>>w[i]>>c[i];  
     
	 for(i=1;i<=n;i++)		
	  for(j=V;j>=w[i];j--)//從V開始,這是個技巧,我在這就走了很多彎路,有興趣的同學可以思考                                 一下 
	    
	  F[j]=max(F[j],F[j-w[i]]+c[i]);
	  
 	  cout<<F[V];
 	}
 }
int max(int x,int y)
 {
 	
 	return x>y?x:y;
 }

另外我想說的是,大家可以換個角度思考問題,可以從物品的價值著手!而不是從物品的重量,在某些

特定的條件下,這個是很好用的!

F[i][c]------對於前i物品而言,使揹包裝上c價值的物品,所需的最小體積!

核心方程:

 F[i][c] = min { F[i-1][c] , F[i-1][c-c[i]] + w[i]  }

對於第i件物品,你可以選擇把它裝入揹包,還可以選擇前i-1件物品對於裝入價值為c的

揹包的最小體積的最優解,

裝入體積為V的F[i][c]中最大的C就是最優解,即對於裝入V體積的東西,可以獲得的最大價值!

問題得到了解決!

程式碼3:

#include<iostream> 
using namespace std;

int w[100];//體積
int v[100];//價值
int F[100];//一維陣列
int Getdata(long int n);//輸入資料
int newdata();//初始化陣列
int min(int a,int b);
int main()
 {
    int n;
    int W;
   while(cin>>n&&cin>>W)
   {
  	 Getdata(n);
  	 newdata();
  	 int i,j;
  	 int max=0;
  	 int vm=0;//暫存價值的大小
  	 for(i=1;i<=n;i++)//為了時間複雜度的考慮我用了滾動陣列
  	 {
  	   vm=vm+v[i];
  	   for(j=vm;j>=1;j--)   
		 if(j>v[i])	
  	   	 F[j]=min(F[j],F[j-v[i]]+w[i]);	 
  	   	 else F[j]=min(F[j],w[i]);   	 
         }
    for(i=1;i<=vm;i++)//找出體積為V的C最大的那個元素
    {
       if((F[i]<=W)&&(i>max)) 
         max=i;       
    }
   cout<<max<<endl;
    }
  return 1;
  } 
int Getdata( int n)
 {
   int i;
   for(i=1;i<=n;i++)
    cin>>w[i]>>v[i];
    return 1;
 }
int newdata()//把陣列初始化為最大值
{
  int i;
  for(i=0;i<100;i++)	
   F[i]=10000;
   return 1;
}
int min(int a,int b)
{
  if(a>b) return b;
  else return a;
}

大家有興趣的話可以做一下這道題:0-1揹包實戰題

如果大家有問題,可以私聊我,我一定會回答的!共同學習,進步,哈哈!

相關推薦

0-1揹包問題滾動陣列動態規劃解決

接觸了很多的0-1揹包的問題,這個問題是動態規劃的經典題,總結一下,加深自己的印象,也 為大家做個參考,對blog有問題可以直接評論,我會盡快的回答! 題目:有N件物品和一個容量為V的揹包,第i件物品的體積w[i],價值是c[i],求解將那些物品裝入揹包 可使這些物品的費

0-1揹包:使用滾動陣列時為何要逆序列舉

問題簡述:有一揹包,最大體積是10,有三個物品,體積分別是3,4,5,重量分別是4,5,6,求在不超過揹包體積的前提下,所放物品的最大重量是多少。 答:最大重量是11,選擇的物品是2和3,其體積是9,小於揹包體積10 我們已經知道,對於0-1揹包問題,我們可以使用動態規劃

0-1揹包問題簡單實現程式碼(動態規劃

import java.util.Scanner; /** * @ClassName Backpack * @Description 0-1揹包問題 * @Author lzq * @Date 2018/12/6 17:51 * @Version 1.0 **/ class

【HDU - 2546】飯卡 (dp0-1揹包貪心思想)

電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷餘額。如果購買一個商品之前,卡上的剩餘金額大於或等於5元,就一定可以購買成功(即使購買後卡上餘額為負),否則無法購買(即使金額足夠)。所以大家都希望儘量使卡上的餘額最少。  某天,食堂中有n種菜出售,每種菜可購買一次。已知每種菜

動態規劃0-1揹包問題鋼條切割

動態規劃 首先說說動態規劃:動態規劃與分治法相似,都是組合子問題的解來解決原問題的解,與分治法的不同在於:分治法的子問題是相互獨立存在的,而動態規劃應用於子問題重疊的情況。 設計動態規劃演算法的步驟: 1、刻畫一個最優解的結構特徵 2、遞迴地定義最優解的

0/1揹包問題(遞迴解決遞推解決

0-1揹包問題:  有N件物品和一個容量為V的揹包。第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。  這個問題的特點是:每種物品只有一件,可以選擇放或者不放。 輸入格式:V,NW1,V1W2,V2.

51Nod1085 0-1揹包(一維和二維陣列實現)

揹包是典型的動態規劃問題,關於揹包問題的詳解,推薦部落格:點選開啟連結(這篇部落格有點錯誤,程式碼for迴圈裡錯了,不過講解 的很詳細) 題目如下: 在N件物品取出若干件放在容量為W的揹包裡,每件物品的體積為W1,W2……Wn(Wi為整數),與之相對應的價值為P1,P2……Pn(Pi為整數)

0-1揹包與完全揹包 SDNUOJ1033採藥(一維陣列)1043採藥2(一維陣列

1033(一維陣列)(揹包容量 j 逆序列舉)0-1揹包 #include<iostream> #include<cstring> #include<cmath> using namespace std; #define N 1005 int v[N]

OpenCV 4.0.1 和 3.4.5 釋出Intel 開源的計算機視覺庫

   OpenCV 4.0.1 和 3.4.5 已釋出,OpenCV 是 Intel 開源的計算機視覺庫。它由一系列 C 函式和少量 C++ 類構成,實現了影象處理和計算機視覺方面的很多通用演算法。OpenCV 擁有包括 300 多個 C 函式的跨平臺的中、高層 API。 這兩

java 泛型詳解(普通泛型、 萬字元、 泛型介面泛型陣列泛型方法泛型巢狀)

JDK1.5 令我們期待很久,可是當他釋出的時候卻更換版本號為5.0。這說明Java已經有大幅度的變化。本文將講解JDK5.0支援的新功能-----Java的泛型. 1、Java泛型  其實Java

模擬退火演算法解決0-1揹包問題

clear clc a = 0.95 k = [5;10;13;4;3;11;13;10;8;16;7;4]; k = -k; % 模擬退火演算法是求解最小值,故取負數 d = [2;5;18;3;2;5;10;4;11;7;14;6]; restriction = 46;

通過埠1433連線到主機127.0.0.1的 TCP/IP 連線失敗錯誤:“connect timed out”的解決方法

解決方案: 1.   開啟SQLServer 配置管理器------->SQLServer for MSQLSERVER------->TCP/IP------->如果沒有啟動,則啟動------->右鍵屬性------->IPAddres

osx升級到10.10後pod install報錯終於解決的方法

... tar font tails http fat error: hat space 先依照這個文章做:http://blog.csdn.net/dqjyong/article/details/37958067 大概過程例如以下: Open Xcode 6O

Django-views戶認證login_requierd()

strong ron 驗證碼錯誤 alt view sta cnblogs img close 分別是認證,登入,註銷的功能 authenticated():驗證是否登錄 user = authenticate(username=‘someone‘,password

UX術語幸運飛艇源碼下載詳解:任務流戶流流程圖以及其它全新術語

希望 演示 重要 職位 flow 重新 生成 img 所有 用戶幸運飛艇源碼下載【大神源碼論壇】dsluntan.com 【布丁源碼論壇】budingbbs.com 企娥3393756370 體驗擁有一長串專業的術語和可交付內容。當在線查看UX相關職位描述時,所羅列的這類

洛谷P2900 [USACO08MAR]土地征Land Acquisition(動態規劃斜率優化決策單調性線性規劃單調隊列)

tps include 寫法 lan clas com mat 成了 dong 用兩種不一樣的思路立體地理解斜率優化,你值得擁有。 題意分析 既然所有的土地都要買,那麽我們可以考慮到,如果一塊土地的寬和高(其實是蒟蒻把長方形立在了平面上)都比另一塊要小,那麽肯定是直接並購,

陣列-BAT面試經典試題:絕對眾數零子陣列最大子陣列

1.絕對眾數問題 定義:給定N個數,稱出現次數最多的數為眾數:若某眾數出現的次數大於N/2,稱該眾數為絕對眾數。 如:A={1,2,1,3,2}中,1和2都是眾數,但都不是絕對眾數;A={1,2,1,3,1}中,1是絕對眾數。 已知給定的N個整數存在絕對眾數,以最低的時空負責度計算該

逆序對的三種求法(歸併排序樹狀陣列線段樹)

求逆序對個數的三種方法 逆序對: 對於一個序列 $a_1$,$a_2$,$a_3$..$a_n$,如果存在$a_i$>$a_j$且i<j,則$a_i$和$a_j$為一個逆序對。 這裡將介紹3種求逆序對對數的方法。 在此之前,預設為你已經會了歸併排序,樹狀陣列和線段樹。(不會的可以百度學習一下)

0-1揹包回溯

限定條件: 如果放入該物品<剩餘揹包容量則回溯。 如果當前價值+剩餘容量下剩餘物品的最大價值<當前最大價值則回溯。(剩下在怎麼放都不會比當前最大價值大,就沒必要算了) 測試: 第一行分別輸入物品數量n與揹包容量c 用例: 10 30095 8975 5923 1973 4350 100

彈層蒙版(mask)ios滾動穿透我們專案的解決方案

問題描述 專案開發遇到一個ios獨有的問題,在wkwebview中穩定復現 問題: 彈出一個蒙版,當在蒙版上面滑動的時候蒙版後面的內容滾動了 這當然是ios的bug,但是經過我們測試iphone7也會復現這個問題,所以沒辦法需要相容。 百度了下好多思路 方法1: 直接禁用滾動容器的overflow,