01-ナップサック問題(バックトラッキング方法)

バックトラッキングと剪定を使用した0-1ナップサック問題。

入力:nc、nはアイテムの数、cはバックパックの容量です。

 次の各行はv [i]、w [i]です。

バックパックの容量の下での最大合計アイテム値はいくらですか?

#include<iostream>
#include<vector>
using namespace std;
int n, c,bestv;
vector<int>x;
vector<int>bestx;
//枚举
void backtrace(vector<int>& v, vector<int>& w,int cw,int cv,int t)
{
	if (t > n)
	{
		if (bestv < cv)
		{
			bestv = cv;
			for (int i = 1; i <= n; i++)
				bestx[i] = x[i];
		}
		return;
	}
	if (cw + w[t] <= c)
	{
		x[t] = 1;
		cw += w[t];
		cv += v[t];
		backtrace(v, w, cw, cv, t + 1);
		cv -= v[t];
		cw -= w[t];
	}
	x[t] = 0;
	backtrace(v, w, cw, cv, t + 1);

}
//剪枝
void backtrace_1(vector<int>& v, vector<int>& w, int cw, int cv, int rp,int t)
{
	if (t > n)
	{
		if (bestv < cv)
		{
			bestv = cv;
			for (int i = 1; i <= n; i++)
				bestx[i] = x[i];
		}
		return;
	}
	rp -= v[t];
	if (cw + w[t] <= c)
	{
		x[t] = 1;
		cw += w[t];
		cv += v[t];
		backtrace(v, w, cw, cv, t + 1);
		cv -= v[t];
		cw -= w[t];
	}
	if (cv + rp > bestv)
	{
		x[t] = 0;
		backtrace(v, w, cw, cv, t + 1);
	}
	rp += v[t];
}
void visit(vector<int>& bestx)
{
	for (int i = 0; i < bestx.size(); i++)
		if(bestx[i])
			cout <<i<< " ";

}
int main()
{
	while (cin >> n>>c)
	{
		vector<int>v;
		vector<int>w;
		int rp = 0;
		x = vector<int>(n + 1, 0);
		bestx= vector<int>(n + 1, 0);
		int t_val, t_weight;
		for (int i = 0; i <= n; i++)
		{
			if (!i)
			{
				v.push_back(0);
				w.push_back(0);
			}
			else
			{
				cin >> t_val >> t_weight;
				v.push_back(t_val);
				w.push_back(t_weight);
				rp += t_val;
			}
			
		}
		int cw, cv;
		cw = 0;
		cv = 0;
		cout << rp << endl;
		//backtrace(v, w, cw, cv, 1);
		backtrace_1(v, w, cw, cv, rp,1);
		cout << bestv << endl;
		visit(bestx);
		
	}
	return 0;
}
/*
4 7
9 3 
10 5
7 2
4 1
*/

 

おすすめ

転載: blog.csdn.net/weixin_40823740/article/details/109642072