算法设计与分析---回溯法

算法设计与分析—回溯法

回溯概念:以深度优先的方式搜索解空间的算法成为回溯法;
回溯法算法框架分类:
1)递归回溯
2)迭代回溯
3)子集树算法框架
4)排列数算法框架

问题一,回溯法解决0-1背包问题

问题描述:
n个物品装入容量为c的背包里面,物品不可以切割,问可以装入的最大价值为多少?
input:
输入一个正整数n和一个double数c(n为物品个数,c为背包容量)
接下来n行每行输入:
物品价值 物品重量
output:
输出最大价值
input_case:

5 5
1 2
3 2
5 6
1 1
2 1

output_case:

bestPrice:6.000000

code:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<set>
using namespace std;
#define   INF   9999
double bestPrice=0;//最优价格 
double now_weight=0;//当前背包总重量 
double now_Price=0;//当前背包总价值 
double limted=0;//背包的重量限制 

int put[INF]={
    
    0};//转入为1,没装入为0 

typedef struct Product{
    
    //该结构体存放物品信息 
	double weight;
	double value;
	int index;
	double prep;
}Product;

double bound(int i,Product *a,int n){
    
    //作用:剪枝 
	double sur_weight=limted-now_weight;
	double max_price=now_Price;
	
	while(i<n&&a[i].weight<=sur_weight){
    
    
		max_price+=a[i].value;
		sur_weight-=a[i].weight;
		i++;
	}
	
	if(i<n){
    
    
		max_price+=a[i].prep*sur_weight;
	}
	
	return max_price;
}

void backTrack(int i,int n,Product *a){
    
    //回溯函数 
	if(i>=n){
    
    
		bestPrice=now_Price;
		return ;
	}
	
	if(a[i].weight+now_weight<=limted){
    
    
		now_weight+=a[i].weight;
		now_Price+=a[i].value;
		put[a[i].index]=1;
		backTrack(i+1,n,a);
		now_weight-=a[i].weight;
		now_Price-=a[i].value;
	}
	
	if(bound(i+1,a,n)>bestPrice){
    
    //符合条件遍历右子树 
		backTrack(i+1,n,a);
	}
}

bool cmp_prep(Product P1,Product P2){
    
    //对价格的比较函数 (单位价格大到小) 
	if(P1.prep==P2.prep){
    
    
		return P1.index<P2.index;
	}else{
    
    
		return P1.prep>P2.prep;
	}
}

int main(){
    
    
	
	int n;
	cin>>n>>limted;//输入物品个数和背包容量 
	Product a[n];
	for(int i=0;i<n;i++){
    
    //依次输入各个物品的价值和重量 
		cin>>a[i].value>>a[i].weight;
		a[i].index=i+1;
	}
	
	sort(a,a+n,cmp_prep);//按照单位价格从大到小排序 
	backTrack(0,n,a);
	printf("bestPrice:%lf\n",bestPrice);	
	return 0;
}

问题二,n后问题

问题描述:
对于n*n的棋盘,放置n个皇后,要求每个皇后之间不能同行,不能同列,不能同对角线,问一共有多少种方案
input:
输入一个正整数num为问题规模(num<=13)num太大就超时了!!!
output:
输出对应的解的个数
input_case:

8

output_case:

92

code:

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
int cnt;
int ans[13];//打表,存放答案
int size[13];//size[i]=j;意味着i行j列放置了皇后

void dfs(int n,int N){
    
    //深度优先搜索,递归实现
	int flag;
	if(n==N+1){
    
    //递归边界
		cnt++;
		return ;
	}
	
	for(int i=1;i<=N;i++){
    
    
		size[n]=i;
		flag=1;
		for(int j=1;j<n;j++){
    
    
			if((abs(n-j)==abs(size[j]-i))||(size[j]==i)){
    
    //不满足条件的情况flag为0
				flag=0;
				break;
			}
		}
		if(flag){
    
    //递归
			dfs(n+1,N);
		}
	}
}

int main(){
    
    
	for(int i=1;i<=13;i++){
    
    
		cnt=0;
		memset(size,0,sizeof size);
		dfs(1,i);
		ans[i]=cnt;
	}
	
	int num;
	scanf("%d",&num);
	printf("%d\n",ans[num]);
	return 0;
}

:(num<=13时各个问题的解)

规模   方案数
1        1  
2        0  
3        0  
4        2  
5        10  
6        4  
7        40  
8        92  
9        352  
10       724  
11       2680  
12       14200  
13       73712  

猜你喜欢

转载自blog.csdn.net/timelessx_x/article/details/115187181