王道機試 第十二章 動態規劃 12.5 揹包問題(0-1揹包,完全揹包,多重揹包)

王道機試 第十二章 動態規劃 12.5 揹包問題

1、0-1揹包

0-1揹包的關鍵特點:每種物品至多選一次),要麼選要麼不選(0/1次)

例題12.7 點菜問題(北京大學複試上機題)
  • 注意事項
  • 揹包數組的範圍——和容量C相關,定義maxm=C+5
  • 內層循環倒序
    原因:
    0-1揹包問題的原始DP方程dp[i][j]=max(dp[i1][j],dp[i1][jw[i]+v[i]])dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i] + v[i]])。由此可知,在第ii輪更新dp[i][j]dp[i][j]時,使用的是第i1i - 1輪的dp[i1][jw[i]]dp[i - 1][j - w[i]]的數值。即:在第ii輪必須先更新dp[i][j]dp[i][j],然後才輪到dp[i1][jw[i]]dp[i - 1][j - w[i]]更新,因此必須jj倒序遞減循環,以保障更新順序

0-1揹包問題的C++核心代碼如下:

  • 初始化:
const int maxm = 1005; // 揹包容量+5
int dp[maxm]; // dp數組
memset(dp, 0, sizeof(dp)); // 初始值
  • 遞推(內層循環倒序):
for (int i = 1; i <= n; i++){
			for (int j = C; j >= w[i]; j--){
				dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
			}
		}
  • 結果輸出
cout << dp[C] << endl; // C爲揹包容量

本問題的完整C++代碼如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn = 105;
const int maxm = 1005;
int dp[maxm]; 
int w[maxn], v[maxn]; // 重量,價值

int main()
{
	int C, n;
	while (cin >> C >> n){
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= n; i++){
			cin >> w[i] >> v[i];
		}
		for (int i = 1; i <= n; i++){
			for (int j = C; j >= w[i]; j--){
				dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
			}
		}
		cout << dp[C] << endl;
	}	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章