余祥宣, 崔国华, 邹海明. 计算机算法基础.3版[M]. 华中科技大学出版社, 2006.
P233-234 算法9.8
程序的输入是一个名字为input.txt的文件,保存时注意编码格式再VS上运行的话要保存为ANSI编码,如果需要的话我可以上传一份
6 4
10 10 12 18
2 4 6 9
#include<iostream>
#include<fstream>
using namespace std;
#define MAX 15
#define _e 0.0001
struct NODE { //结点数据结构
NODE *PARENT=NULL; //指向父结点指针
NODE *next=NULL; //后继结点指针
int LEVEL=-1; //结点的所在的层数
int TAG=-1; //左右孩子的标志,1为左孩子,0为右孩子
int CU=-1; //目前背包剩余空间
int PE=-1; //目前已装入物品有效益值
int LB=-1; //结点的下界值
float UB=-1; //结点的上界值
};
int P[MAX];
int W[MAX];
int N;//物品数量
int M;//背包最大空间
NODE *head; //活动结点队列队头
NODE *ANS;
void INIT() //初始化队列
{
head = new(NODE);
head->next = NULL;
ANS = new(NODE);
}
void ADD(NODE *node)
{
node->next = head->next;
head->next = node;
}
NODE* GETNODE()
{
return new(NODE);
}
void NEWNODE(NODE *par, int lev, int t, int cap, int prof, int lb,int ub)
{
NODE *I=GETNODE();
I->PARENT = par;
I->LEVEL = lev;
I->TAG = t;
I->CU = cap;
I->PE = prof;
I->LB = lb;
I->UB = ub;
ADD(I);
}
NODE* NEXLIVENODE() //下一扩展结点(取下限LBB最大结点)
{
NODE *p = head->next, *choice = p;
int LBB = p->LB;
while (p)
{
if (p->LB > LBB)
choice = p;
p = p->next;
}
return(choice);
}
void DEQUEUE(NODE* node) //将结点i从优先队列中删除
{
NODE *pre = head, *p = head->next;
while (p != node)
{
pre = p;
p = p->next;
}
pre->next = p->next;
}
NODE* LARGEST(NODE *node)
{
node = NEXLIVENODE(); //下一扩展结点
DEQUEUE(node); //将结点从队列中删除
return node;
}
void FINISH(int L, NODE *ANS, int N)
{
cout << "VALUE OF OPTIMAL FILLING IS\n";
cout<<L;
cout << "\nOBJECT IN KNAPSACK ARE\n";
for (int j = N; j >= 1; j--)
{
if (ANS->TAG == 1)
cout << 'x' << j << ' ';
ANS = ANS->PARENT;
}
cout << endl;
}
void LUBOUND(int P[], int W[], int rw, int cp, int N, int k, int &LBB, float &UBB)
{
int c;
LBB = cp;
c = rw;
for (int i = k; i <= N; i++)
{
if (c < W[i])
{
UBB = (float)(LBB + c * P[i] / W[i]);
for (int j = i + 1; j <= N; j++)
{
if (c >= W[j])
{
c = c - W[j];
LBB = LBB + P[j];
}
}
return;
}
c = c - W[i];
LBB = LBB + P[i];
}
UBB = (float)LBB;
}
void LCKNAP(int P[], int W[], int M,int N,float e)
{
int L, LBB=0, cap, prof;
float UBB = 0;
int X;
INIT();
NODE *E=GETNODE();
E->PARENT = 0;
E->LEVEL = 1;
E->CU = M;
E->PE = 0;
E->TAG = 0;
LUBOUND(P, W, M, 0, N, 1, LBB, UBB);
L = LBB - e;
E->UB = UBB;
E->LB = LBB;
int i;
while (E->UB>L)
{
i = E->LEVEL;
cap = E->CU;
prof = E->PE;
if (i == N + 1)
{
if (prof > L)
{
L = prof;
ANS = E;
}
}
else
{
if (cap >= W[i])
NEWNODE(E, i + 1, 1, cap - W[i], prof + P[i], E->LB,E->UB);
LUBOUND(P, W, cap, prof, N, i + 1, LBB, UBB);
if (UBB > L)
{
NEWNODE(E, i + 1, 0, cap, prof, LBB, UBB);
if (LBB - e > L)
L = LBB - e;
}
}
if (head->next == NULL)
break;
E=LARGEST(E);
}
FINISH(L, ANS, N);
}
int main()
{
ifstream in("input.txt");
in >> M >> N;
P[0] = W[0] = 0;
for (int i = 1; i <=N; i++)
in >> P[i];
for (int i = 1; i <= N; i++)
in >> W[i];
cout << "各个物品的价值和重量为:" << endl;
cout << "Name\tP\tW" << endl;
for (int i = 1; i <= N; i++)
cout << "x" << i << "\t" << P[i] << "\t" <<W[i] << endl;
cout << "M=" << M << "\tN=" << N<<endl;
LCKNAP(P, W, M, N,_e);
cout << endl;
system("pause");
return 0;
}
运行结果