书包问题

#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;
				}
		}
	}
}	 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值