バックトラッキングと剪定を使用した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
*/