经典的0-1背包用动态规划解,加上什么条件之后,会变得不能用动态规划?举个例子,谢谢,我有用

2024-11-22 19:20:37
推荐回答(2个)
回答1:

下面是我自己写的代码,用动态规划的方法解0/1背包问题。用VC6编译运行正确。供参考。
//这是头文件 knapsack.hpp
#ifndef KNAPSACK_HPP
#define KNAPSACK_HPP

using namespace std;

const int MAX_COUNT_OF_WIDGETS = 16;
const int MAX_CAPACITY_OF_KNAPSACK = 15;
// int CAPACITY_OF_KNAPSACK = 0;
// int COUNT_OF_WIDGETS = 0;
/* This struct widget is defined. */
struct Widget
{
int m_iID;
int m_iVolume;
int m_iValue;
bool m_bSelected;
};

/* This struct knapsack is defined */
struct Knapsack
{
int m_iCapacity;
int m_iValue;
};

/*
* This struct will be used in DynamicPrograming().
* m_iMaxValue indicates the maximum value can be achieved when the count of
* widgets is i and the capacity of the knapsack is j;
* m_bSelected indicates to achieve the maximum value whether the i-th widget
* is selected under the same condition stated above.
*/
struct MemeorizeMark
{
int m_iMaxValue;
bool m_bSelected;
};

class SolveKnapsack
{
public:
bool Init();
bool DynamicProgramming();
void PrintMaxValue()const;
void PrintSelection()const;

private:
Knapsack m_Knapsack;
Widget m_Widget[MAX_COUNT_OF_WIDGETS];
int m_iCountOfWidgets;
MemeorizeMark m_MemeorizeMark[MAX_COUNT_OF_WIDGETS][MAX_CAPACITY_OF_KNAPSACK];
};

#endif

========================================================
========================================================
//这是cpp文件 knapsack.cpp
#include
#include "knapsack.hpp"

using namespace std;

bool SolveKnapsack::Init()
{
/* initialize the knapsack */
cout << "Pls input the capacity of knapsack(0 < capacity <= " << MAX_CAPACITY_OF_KNAPSACK << "): " << endl;
cin >> m_Knapsack.m_iCapacity;
m_Knapsack.m_iCapacity += 1;

if ((0 >= m_Knapsack.m_iCapacity) || ((MAX_CAPACITY_OF_KNAPSACK + 1) < m_Knapsack.m_iCapacity))
{
cout << "Capacity is not correct" << endl;
return false;
}
else
{
m_Knapsack.m_iValue = 0;
}

/* initialize the widgets */
cout << "Pls input the count of widgets(0< count <= " << MAX_COUNT_OF_WIDGETS << "): " << endl;
cin >> m_iCountOfWidgets;
m_iCountOfWidgets += 1;

if ((0 >= m_iCountOfWidgets) || ((MAX_COUNT_OF_WIDGETS + 1) < m_iCountOfWidgets))
{
cout << "count of widgets is not correct" << endl;
return false;
}
else
{
for (int i = 1; i < m_iCountOfWidgets; i++)
{
m_Widget[i].m_iID = i;

cout << "Pls input widget[" << i << "]'s volume:" << endl;
cin >> m_Widget[i].m_iVolume;
if (m_Widget[i].m_iVolume <= 0)
{
cout << "widget's volume is not correct" << endl;
return false;
}

cout << "Pls input widget[" << i << "]'s value:" << endl;
cin >> m_Widget[i].m_iValue;
if (m_Widget[i].m_iValue <= 0)
{
cout << "widget's value is not correct" << endl;
return false;
}

m_Widget[i].m_bSelected = false;
}// end of for
}// end of if

/* initialize the MemeorizeMark */
for (int i = 0; m_iCountOfWidgets > i; i++)
{
for (int j = 0; m_Knapsack.m_iCapacity > j; j++)
{
m_MemeorizeMark[i][j].m_iMaxValue = 0;
m_MemeorizeMark[i][j].m_bSelected = false;
}
}

return true;
}

bool SolveKnapsack::DynamicProgramming()
{
/*
* variable i stands for the current count of widgets;
* variable j stands for the current capacity of knapsack.
*
* The following code segment is to compute the value of the optimal
* solution using dynamic programming.
*/
int i = 0;
int j = 0;
for (i = 1; m_iCountOfWidgets > i; i++)
{
for (j = 1; m_Knapsack.m_iCapacity > j; j++)
{
if (m_Widget[i].m_iVolume <= j)
{

if ((m_MemeorizeMark[i - 1][j - m_Widget[i].m_iVolume].m_iMaxValue + m_Widget[i].m_iValue)
>=
m_MemeorizeMark[i-1][j].m_iMaxValue)
{
m_MemeorizeMark[i][j].m_iMaxValue = m_MemeorizeMark[i - 1][j - m_Widget[i].m_iVolume].m_iMaxValue + m_Widget[i].m_iValue;
m_MemeorizeMark[i][j].m_bSelected = true;
}
else
{
m_MemeorizeMark[i][j].m_iMaxValue = m_MemeorizeMark[i-1][j].m_iMaxValue;
m_MemeorizeMark[i][j].m_bSelected = false;
}
}
else
{
m_MemeorizeMark[i][j].m_iMaxValue = m_MemeorizeMark[i-1][j].m_iMaxValue;
m_MemeorizeMark[i][j].m_bSelected = false;
}
}
}

/*
* The following code segment is to contruct the optimal solution
* from the computed information.
*/
i = m_iCountOfWidgets - 1;
j = m_Knapsack.m_iCapacity - 1;

m_Knapsack.m_iValue = m_MemeorizeMark[i][j].m_iMaxValue;
for ( ; 0 < i; i--)
{
if (true == m_MemeorizeMark[i][j].m_bSelected)
{
m_Widget[i].m_bSelected = true;
j = j - m_Widget[i].m_iVolume;
}
}

return true;
}

void SolveKnapsack::PrintMaxValue()const
{
cout << "Max value is: " << m_Knapsack.m_iValue << endl;
}

void SolveKnapsack::PrintSelection()const
{
for (int i = 1; i < m_iCountOfWidgets; i++)
{
if (true == m_Widget[i].m_bSelected)
{
cout << "Widget[" << i << "] is selected" << endl;
}
}
}

int main()
{
SolveKnapsack SK;
if (true == SK.Init())
{
if (true == SK.DynamicProgramming())
{
SK.PrintMaxValue();
SK.PrintSelection();
}
}

return 0;
}

回答2:

把物品平均分到n个包裹中能否实现,参照vijos上的“双塔问题”