【计算机算法】回溯——n皇后问题、0-1背包问题

n皇后问题

回溯——子集树解决办法

#include<iostream>
#include<cmath>
#include<algorithm> 
using namespace std;

int *x;
int n;//皇后的个数 
int num = 0;//解的个数 

bool constraint(int k){
    
    
	for(int i = 1;i < k;i++){
    
    
		//cout<<"x[i]:"<<x[i]<<",x[k]:"<<x[k]<<",i:"<<i<<",k:"<<k<<endl;
		if((x[i] == x[k]) || ( abs(x[i] - x[k]) == abs(k - i)))//前面一个条件判断不在同一列上,后面条件判断不在同一对角线上
		//若是满足上述条件中的任意一种就应该返回false,之前写成了&&,所以出现了太多种 
			return false; 
	}
	return true;
}

void output(){
    
    
	cout<<endl;
	cout<<"具体放置位置:"<<endl; 
	for(int i = 1;i <= n;i ++){
    
    
		cout<<"第"<<i<<"行放在第"<<x[i]<<"列上"<<endl;
	}
}

void swap(int *a,int *b){
    
    
	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
}

void backtrack(int k){
    
    
	if(k > n){
    
    
		num ++;//解法+1 
		output();//输出解 
	}
	else{
    
    
		for(int i = 1;i <= n;i ++){
    
    //n行 
			x[k] = i;
			if(constraint(k)) 
				backtrack(k + 1);
		}
	}
} 

int main(){
    
    
	cout<<"请输入皇后个数:";
	cin>>n;
	x = new int[n + 1];
	backtrack(1);
	cout<<"解法种数:"<<num<<endl;
	delete[] x;
	
	return 0; 
} 

回溯——排列树解决办法

#include<iostream>
#include<cmath>
#include<algorithm> 
using namespace std;

int *x;
int n;//皇后的个数 
int num = 0;//解的个数 

bool constraint(int k){
    
    
	for(int i = 1;i < k;i++){
    
    
		//cout<<"x[i]:"<<x[i]<<",x[k]:"<<x[k]<<",i:"<<i<<",k:"<<k<<endl;
		if((x[i] == x[k]) || ( abs(x[i] - x[k]) == abs(k - i)))//前面一个条件判断不在同一列上,后面条件判断不在同一对角线上
		//若是满足上述条件中的任意一种就应该返回false,之前写成了&&,所以出现了太多种 
			return false; 
	}
	return true;
}

void output(){
    
    
	cout<<endl;
	cout<<"具体放置位置:"<<endl; 
	for(int i = 1;i <= n;i ++){
    
    
		cout<<"第"<<i<<"行放在第"<<x[i]<<"列上"<<endl;
	}
}

void swap(int *a,int *b){
    
    
	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
}

void backtrack(int k){
    
    
	if(k > n){
    
    
		num ++;//解法+1 
		output();//输出解 
	}
	else{
    
    
		for(int i = k;i <= n;i ++){
    
    //n行 
			swap(&x[i],&x[k]);
			if(constraint(k))
				backtrack(k + 1);
			swap(&x[i],&x[k]);
		}
	}
} 

int main(){
    
    
	cout<<"请输入皇后个数:";
	cin>>n;
	x = new int[n + 1];
	for(int i = 1;i <= n;i++){
    
    //进行初始化x,但是子集树是不需要这一步的,因为子集树会在backtrack中放置,而排列树只会在backtrack中交换
		x[i] = i;
	}
	backtrack(1);
	cout<<"解法种数:"<<num<<endl;
	delete[] x;
	
	return 0; 
} 



0-1背包问题

回溯——子集树解决办法

#include<iostream>
using namespace std;

int maxValue = 0;//最大价值
int bagSize;//背包空间 
int n;//物品数量
int *w,*v;//重量数组指针和价值指针
int *nowIn;//现在放入背包中的东西 
int *bestSolution;//最优解 

void output(){
    
    
	int sum = 0;
	int weight = 0;
	for(int i = 1;i <= n;i++){
    
    
		if(nowIn[i] == 1){
    
    
			sum += v[i];
			weight += w[i];
		}
	}
	if(sum > maxValue && weight <= bagSize){
    
    //如果背包中的物品价值大于目前最大价值 
		maxValue = sum;//赋值给最大价值
		for(int i = 1;i <= n;i++){
    
    //赋值给最优解数组 
			bestSolution[i] = nowIn[i];
		}
		
	}
}

void backtrack(int k) {
    
    
	int size = 0;
	if(k > n){
    
    
		output();
	}
	else{
    
    
		for(int i = 1;i >= 0;i --){
    
    
			nowIn[k] = i;
			
			if(nowIn[k] == 0)//如果不选择当前节点,直接进入下一个节点 
				backtrack(k + 1);
			
			else{
    
    
				for(int j = 1;j <= n;j++){
    
    //计算当前背包中的容量 
					if(nowIn[j] == 1){
    
    
						size += w[j];
					}
				}
				if(size <= bagSize){
    
    //如果当前背包中物品重量小于背包的最大重量,可以继续回溯 
					size = 0;
					backtrack(k + 1);//放置下一个 
				}	
			}
		}
	}
}
 
int main(){
    
    
	cout<<"请输入背包的空间:";
	cin>>bagSize; 
	cout<<"请输入共有多少个物品:";
	cin>>n;
	w = new int[n + 1];
	v = new int[n + 1];
	nowIn = new int[n + 1];
	bestSolution = new int[n + 1]; 
	cout<<"请输入各个物品的重量"<<endl;
	for(int i = 1;i <= n;i++) {
    
    
		cout<<"第"<<i<<"个物品的重量:";
		cin>>w[i]; 
	}
	for(int i = 1;i <= n;i++){
    
    
		cout<<"第"<<i<<"个物品价值:";
		cin>>v[i]; 
	}
	for(int i = 1;i <= n;i++){
    
    
		nowIn[i] = 0;
	}
	backtrack(1);
	
	//输出 
	cout<<"选中第" ;
	for(int i = 1;i <= n;i++){
    
    
		if(i != n && bestSolution[i] == 1)
			cout<<i<<",";
		else if(i == n && bestSolution[i] == 1)
			cout<<i;
	}
	cout<<"个物品 ";
	cout<<"maxValue:"<<maxValue<<endl; 
	
	
	return 0;
}

Guess you like

Origin blog.csdn.net/passer__jw767/article/details/111657351