天天看點

多重背包---二進制拆分---java小知識前言一、什麼是多重背包?二、二進制拆分三、例題及代碼實作總結

💬推薦一款模拟面試、刷題神器,從基礎到大廠面試題👉點選跳轉刷題網站進行注冊學習

文章目錄

  • 前言
  • 一、什麼是多重背包?
  • 二、二進制拆分
  • 三、例題及代碼實作
  • 總結

前言

背包問題分為:01背包,完全背包以及多重背包,本文主要講解多重背包。

01背包以及01背包的優化講解:

01背包:https://blog.csdn.net/m0_55486529/article/details/123806820

01背包優化:https://blog.csdn.net/m0_55486529/article/details/123831655

完全背包:https://blog.csdn.net/m0_55486529/article/details/123854386

提示:以下是本篇文章正文内容,下面案例可供參考

一、什麼是多重背包?

給定n種物品,每種物品都有重量w,和價值v;,第i種物品有c;個。背包容量為W,求解在不超過背包容量的情況下如何放置物品,使背包中物品的價值之和最大。

首先,01背包是指物品的個數為一,完全背包是物品的個數沒有限制(無窮多),多重背包就是完全背包和01背包的組合,當物品個數c[ i ] * 重量w [ i ] >= 背包容量 j時,相當于完全背包,當 c[ i ]*w[ i ]<j 時我們可以轉化為01背包解決問題。

可以通過暴力拆分或二進制拆分将多重背包問題轉化為01背包問題,也可以通過數組優化解決可行性問題。

其中,完全背包就像完全背包一樣解決(上面有連結,可以學習完全背包)

最難的就是怎麼轉化為01背包,這裡我們使用二進制拆分。

二、二進制拆分

多重背包---二進制拆分---java小知識前言一、什麼是多重背包?二、二進制拆分三、例題及代碼實作總結

其實二進制拆分,我們可以把它了解成将c[i]個物品打包分成 幾份,相當于把100個蘋果分成好幾箱,每一箱的個數是2的幾次方,最後如果不夠就把剩下的放一箱。

三、例題及代碼實作

多重背包---二進制拆分---java小知識前言一、什麼是多重背包?二、二進制拆分三、例題及代碼實作總結

代碼如下:

public class test {

	public static void main(String[] args) {
		// TODO 自動生成的方法存根
		int[] w= {2,5,4,2,3};  //單個物品重量
		int[] v= {6,3,5,4,6};  //單個物品價值
		int[] c= {2,2,5,5,4};  //物品個數
		System.out.println(bagkiller(c,w,v,10));
	}
	public static int bagkiller(int[] c,int[] w,int[] v,int n) {
		int [] dp=new int[n+1];
		for (int i=0;i<w.length;i++) {   
			if (c[i]*w[i]>=n) {  //如果物品個數c[ i ] * 重量w [ i ] >= 背包容量 j時,相當于完全背包
				for (int j=w[i];j<=n;j++) {  //轉化為完全背包
					dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
			}
			}else {
				for (int k=1;c[i]>0;k<<=1) {  //二進制拆分
					int x=Math.min(c[i], k);  //判斷剩餘的個數是否足夠二進制拆分
					for (int j=n;j>=w[i];j--) {   //轉化為01背包
						dp[j]=Math.max(dp[j],dp[j-w[i]*x]+v[i]*x);   
					}
					c[i]-=x;
				}
			}
		}
		return dp[n];
	}
}
           

結果:

總結

以上就是今天要講的内容,本文僅僅簡單介紹了完全背包的概念,以及常用解決方法,以及二進制拆分的基本知識。