// 17x1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// 分支界定法:最大装载问题(使用FIFO)
#include <iostream.h>
#include "lqueue.h"
// 所有参数里,最重要的是当前路径的累计权重wt,其余都是辅助参数
template<class T>
void AddLiveNode(LinkedQueue<T> &Q, T wt, T& bestw, int i, int n)
{
if (i == n) {// 到达叶节点
if (wt > bestw) bestw = wt;
}
// 如果不是叶节点,则将节点权值wt加入队列Q
else Q.Add(wt); // 非叶节点
}
// 使用FIFO分支界定法返回最优装载值
template<class T>
T GetMaxLoading(T w[], T c, int n)
{
LinkedQueue<T> Q; // 活结点队列
// 为第一层初始化
Q.Add(-1); // 用来标记本层的尾部,但第一次添加的时候其实是在头部
int i = 1; // E-节点的层,这里使用迭代法,而不是递归
T Ew = 0, // E-节点的权重(节点自身与所有祖先的权重的累加)
bestw = 0; // 目前的最优值
// 搜索子集空间树
while (true) {
cout << "Ew=" << Ew << ", i="<< i << endl;
// 检查E-节点的左孩子
// Ew为所有祖先的权重的累计,加上w[i]当前节点的权重
if (Ew + w[i] <= c) {
// 新的Ew放在队列里,等待下一轮循环使用
AddLiveNode(Q, Ew+w[i], bestw, i, n); // x=1时,把祖先+当前节点的左孩子的权重总和,放入队列
}
// 右孩子总是可行的,因为右孩子x=0不取值,目前没有代价
AddLiveNode(Q, Ew, bestw, i, n); // x[i] = 0
Q.Delete(Ew); // 取得下一个E-节点,删除Q队列的头元素,并放到Ew里。
if (Ew == -1) { // 当Ew=-1时,进入层的尾部,代表当前层的所有节点都处理完毕了
if (Q.IsEmpty()) return bestw; // 碰到-1节点之后,队列里没有元素了,那么程序就该结束了
Q.Add(-1); // 每次碰到-1标记进来,代表上一层所有的数据都处理完了,这时为下一层的尾部添加-1标记
Q.Delete(Ew); // 从队列中删除首个元素,同时取得下一个E-节点,准备下个循环使用
i++; // 前一层结束了,当然Ew的层编号i要加1
}
}
}
void main(void)
{
/* int w[6] = {0, 2, 2, 6, 5, 5};
int n = 5;
int c = 16; */
int w[4] = {0, 20, 15, 15};
int n = 3;
int c = 30;
cout << "Max loading is " << GetMaxLoading(w,c,n) << endl;
}
// ------------------lqueue.h文件-----------------------------------------
// header file lqueue.h
// linked queue
#ifndef LinkedQueue_
#define LinkedQueue_
#include "node.h"
#include "xcept.h"
template<class T>
class LinkedQueue {
// FIFO objects
public:
LinkedQueue() {front = rear = 0;} // constructor
~LinkedQueue(); // destructor
bool IsEmpty() const
{return ((front) ? false : true);}
bool IsFull() const;
T First() const; // return first element
T Last() const; // return last element
LinkedQueue<T>& Add(const T& x);
LinkedQueue<T>& Delete(T& x);
// private:
Node<T> *front; // pointer to first node
Node<T> *rear; // pointer to last node
};
template<class T>
LinkedQueue<T>::~LinkedQueue()
{// Queue destructor. Delete all nodes.
Node<T> *next;
while (front) {
next = front->link;
delete front;
front = next;
}
}
template<class T>
bool LinkedQueue<T>::IsFull() const
{// Is the queue full?
Node<T> *p;
try {p = new Node<T>;
delete p;
return false;}
catch (NoMem) {return true;}
}
template<class T>
T LinkedQueue<T>::First() const
{// Return first element of queue. Throw
// OutOfBounds exception if the queue is empty.
if (IsEmpty()) throw OutOfBounds();
return front->data;
}
template<class T>
T LinkedQueue<T>::Last() const
{// Return last element of queue. Throw
// OutOfBounds exception if the queue is empty.
if (IsEmpty()) throw OutOfBounds();
return rear->data;
}
template<class T>
LinkedQueue<T>& LinkedQueue<T>::Add(const T& x)
{// Add x to rear of queue. Do not catch
// possible NoMem exception thrown by new.
// create node for new element
Node<T> *p = new Node<T>;
p->data = x;
p->link = 0;
// add new node to rear of queue
if (front) rear->link = p; // queue not empty
else front = p; // queue empty
rear = p;
return *this;
}
template<class T>
LinkedQueue<T>& LinkedQueue<T>::Delete(T& x)
{// Delete first element and put it in x. Throw
// OutOfBounds exception if the queue is empty.
if (IsEmpty()) throw OutOfBounds();
// save element in first node
x = front->data;
// delete first node
Node<T> *p = front;
front = front->link;
delete p;
return *this;
}
#endif
// --------------------node.h文件-------------
#ifndef Node_
#define Node_
template <class T> class LinkedStack;
template <class T> class LinkedQueue;
template <class T>
class Node {
friend LinkedStack<T>;
friend LinkedQueue<T>;
private:
T data;
Node<T> *link;
};
#endif
// ---------------------xcept.h文件----------------------
// exception classes for various error types
#ifndef Xcept_
#define Xcept_
#include <new.h>
// bad initializers
class BadInitializers {
public:
BadInitializers() {}
};
// insufficient memory
class NoMem {
public:
NoMem() {}
};
// change new to throw NoMem instead of standard behavior
// Visual C++ requires following form of my_new_handler
int my_new_handler(size_t x)
{
throw NoMem();
// even though the following statement is unreachable,
// visual C++ will not compile successfully without it
return 0;
};
_PNH Old_Handler_ = _set_new_handler(my_new_handler);
// improper array, find, insert, or delete index
// or deletion from empty structure
class OutOfBounds {
public:
OutOfBounds() {}
};
// use when operands should have matching size
class SizeMismatch {
public:
SizeMismatch() {}
};
// use when zero was expected
class MustBeZero {
public:
MustBeZero() {}
};
// use when zero was expected
class BadInput {
public:
BadInput() {}
};
#endif