1. 程式人生 > >演算法-揹包問題-動態規劃

演算法-揹包問題-動態規劃

揹包問題

揹包問題分為三類

  • 01揹包問題
  • 完全揹包問題
  • 變態揹包問題

解決的思路都是使用動態規劃,直接上程式碼。

#include <iostream>
#include <algorithm>

using namespace std;
int V[5][9];//代表用二維陣列求解
int V_op[9];//代表用一維陣列求解
int w[] = { 0, 2, 3, 4, 5 };//代表物品佔用空間
int v[] = { 0, 3, 4, 5, 6 };//代表物品價值
int c[] = { 0, 3, 4, 4, 4 };//代表物品數量限制,比如第一件物品最多能拿兩件

void pack01();
void findConsist(int i, int j);
void pack_op();
void pack_full();
void pack_extrme();

int main(){
	//二維陣列,可以查詢包裡的物品
	pack01();

	//一維陣列,比二維陣列佔用空間更小,但是無法直接反解包中物品
	pack_op();

	//揹包完全問題,即每件物品可以有無限多個
	pack_full();

    //揹包問題變態版,即每件物品可以有多個,但是由數量限制
	pack_extrme();

	std::system("pause");
	return 0;
}

void pack01(){
	for (int i = 0; i <= 4; i++){
		V[i][0] = 0;
	}
	for (int j = 0; j <= 8; j++){
		V[0][j] = 0;
	}

	for (int i = 1; i <= 4; i++){
		for (int j = 1; j <= 8; j++){
			if (j < w[i]){
				V[i][j] = V[i - 1][j];
			}
			else{
				V[i][j] = max(V[i - 1][j], V[i - 1][j - w[i]] + v[i]);
			}
		}
	};

	cout << V[4][8] << endl;

	for (int i = 1; i <= 4; i++){
		for (int j = 1; j <= 8; j++){
			cout << V[i][j] << "\t";
		}
		cout << endl;
	}

	findConsist(4, 8);
}

void findConsist(int i, int j){
	if (i == 0){
		return;
	}
	if (V[i][j] == V[i - 1][j]){
		cout << "商品" << i << "不在包裡" << endl;
		findConsist(i - 1, j);
	}
	else{
		cout << "商品" << i << "在包裡" << endl;
		findConsist(i - 1, j - w[i]);
	}
}

void pack_op(){
	for (int i = 0; i < 9; i++){
		V_op[i] = 0;
	}
	for (int i = 0; i < 5; i++){
		for (int j = 8; j >= w[i]; j--){
			V_op[j] = max(V_op[j], V_op[j - w[i]] + v[i]);
		}
	}

	for (int i = 1; i < 9; i++)
		cout << V_op[i] <<"\t";
	cout << endl;
}

void pack_full(){
	for (int i = 0; i < 9; i++){
		V_op[i] = 0;
	}
	for (int i = 0; i < 5; i++){
		for (int j = w[i]; j <= 8; j++){
			V_op[j] = max(V_op[j], V_op[j - w[i]] + v[i]);
		}
	}

	for (int i = 1; i < 9; i++)
		cout << V_op[i] << "\t";
	cout << endl;
}

void pack_extrme(){
	for (int i = 1; i <= 4; i++)
		for (int j = 8; j >= 0; j--)
		for (int k = 1; k <= c[i]; k++){//c[i]代表每種物品的數量限制,比如物品2最多有兩個
			if (j - k*w[i] < 0) break;
			V_op[j] = max(V_op[j], V_op[j - k*w[i]] + k*v[i]);
		}
	cout << V_op[8] << endl;
}

參考部落格1 參考部落格2