#include <iostream>
using namespace std;
// abstract data type for stack
template <class T> // 栈的元素类型为 T
class Stack {
public: // 栈的运算集
void clear(); // 变为空栈
bool push(const T item); // item入栈,成功则返回真,否则返回假
bool pop(T* item); // 返回栈顶内容并弹出,成功返回真,否则返回假,
bool getTop(T* item); // 返回栈顶内容但不弹出成功返回真,否则返回假,
bool isEmpty(); // 若栈已空返回真
bool isFull(); // 若栈已满返回真
};
// array-based stack: definition and implementation for some methods
template <class T>
class arrStack: public Stack<T> {
private: // 栈的顺序存储
int mSize; // 栈中最多可存放的元素个数
T *st; // 存放栈元素的数组
public:
int top; // 栈顶位置,应小于mSize
public: // 栈的运算的顺序实现
arrStack(int size) { // 创建一个顺序栈的实例
mSize = size;
top = -1;
st = new T[mSize];
}
~arrStack() { // 析构函数
delete [] st;
}
void clear() { // 清空栈内容
top = -1;
}
bool push(const T item) { // 入栈操作的顺序实现
if (top == mSize-1) { // 栈已满
cout << "栈满溢出" << endl;
return false;
}
else { // 新元素入栈并修改栈顶指针
st[++top] = item;
return true;
}
}
bool pop(T* item) { // 出栈的顺序实现
if (top == -1) { // 栈为空
cout << "栈为空,不能出栈操作"<< endl;
return false;
}
else {
*item = st[top--]; // 返回栈顶元素并修改栈顶指针
return true;
}
}
bool getTop(T* item) { // 返回栈顶内容,但不弹出
if (top == -1) { // 栈空
cout << " 栈为空,不能出栈操作"<< endl;
return false;
}
else {
*item = st[top];
return true;
}
}
bool isEmpty() {
return (top == -1);
}
bool isFull() {
return (top == mSize-1);
}
};
bool knap(int s, int n);
bool nonRecKnap(int s, int n);
bool nonRecKnapOpt(int s, int n);
enum rdType {a, b, c};
class knapNode {
friend bool nonRecKnap(int s, int n);
friend bool nonRecKnapOpt(int s, int n);
int s, n; // 背包的承重量和物品的数目
rdType rd; // 返回地址
bool k; // 结果单元
};
// 引入两个与栈中结点类型相同的变量tmp和x作为进出栈的缓冲:
class knapNode tmp, x;
// 定义一个栈变量:
//Stack<knapNode> st(20);
int w[5] = {2,4,4,5,7};
int main() {
int s;
cin >> s;
cout << "recursion" << endl;
if (knap(s, 5))
cout << "Have solution" << endl;
else cout << "No solution" << endl;
cout << "non recursion" << endl;
if (nonRecKnap(s, 5))
cout << "Have solution" << endl;
else cout << "No solution" << endl;
cout << "non recursion optimization" << endl;
if (nonRecKnapOpt(s, 5))
cout << "Have solution" << endl;
else cout << "No solution" << endl;
cin >> s;
return 0;
}
//递归版的背包问题
bool knap(int s, int n) {
if (s == 0)
return true;
if ((s < 0)||(s>0 && n <1))
return false;
if (knap(s-w[n-1], n-1)) {
cout << w[n-1];
return true;
}
else knap(s, n-1);
}
// 非递归的机械版
bool nonRecKnap(int s, int n) {
arrStack<knapNode> st(20);
tmp.s = s, tmp.n = n, tmp.rd = a; // 非递归调用入口
st.push(tmp);
label0: // 递归调用入口
st.pop(&tmp);
if (tmp.s == 0 ) {
tmp.k = true; // 修改栈顶的结果单元k
st.push(tmp);
goto label3;
}
if ((tmp.s < 0) || (tmp.s > 0 && tmp.n < 1)) {
tmp.k = false; // 修改栈顶的结果单元k
st.push(tmp);
goto label3;
}
st.push(tmp);
x.s = tmp.s-w[tmp.n-1]; // 按照规则1进行压栈处理
x.n = tmp.n -1;
x.rd = b;
st.push(x);
goto label0;
label1: // 规则1对应的返回处理
st.pop(&x); // 查看栈顶,根据其内容分情况处理
if (tmp.k == true) { // 若某层的结果单元为true
x.k = true; // 把true结果上传给调用方
st.push(x);
cout << w[x.n-1]<<endl; // 并输出对应的物品
goto label3;
}
st.push(x); // 若某层的结果单元为false
tmp.s = x.s; // 当前物品的选择不合适,回溯,调用规则2
tmp.n = x.n - 1; // 按照规则2进行压栈处理
tmp.rd = c;
st.push(tmp);
goto label0;
label2: // 规则2对应的返回处理
st.pop(&x);
x.k = tmp.k; // 结果单元k的内容上传给调用方
st.push(x);
label3: // 递归出口处理
st.pop(&tmp);
switch (tmp.rd) {
case a: return tmp.k; // 算法结束并返回结果
case b: goto label1; // 转向规则1的返回处理处
case c: goto label2; // 转向规则2的返回处理处
}
}
// 非递归的优化版
bool nonRecKnapOpt(int s, int n) {
int t, n0 = n;
bool k = false;
arrStack<knapNode> st(20);
tmp.s = s, tmp.rd = a;
st.push(tmp);
while (!st.isEmpty()) {
t = st.top;
st.getTop(&tmp);
while ((tmp.s >= 0) && (tmp.s <= 0 || n0 > t)){ //处理栈顶元素,以判断是否满足递归出口条件
if (tmp.s == 0 ) {
k = true;
break;
} else { // 尚未递达归出口前,按规则1进行压栈操作
x.s = tmp.s - w[n0 - 1 - t];
x.rd = b;
st.push(x);
}
t = st.top;
st.getTop(&tmp);
}
while (!st.isEmpty()) { // 返回处理
st.pop(&tmp);
t = st.top;
if (tmp.rd == 0) // 算法结束
return k;
if (tmp.rd == 1) // 从规则1返回
if (k == true) // 结果为真则打印对应的物品
cout << w[n0 - 1 - t]<<endl;
else { // 否则回溯,采用规则2进栈
st.getTop(&x);
tmp.s = x.s;
tmp.rd = c;
st.push(tmp);
break;
}
}
}
}
书包问题
最新推荐文章于 2021-04-23 23:20:00 发布