回溯法(01背包问题)dfs bfs 组合树排列树问题 及相应模板

回溯

  • 1.子集树
  • 2. 排列树
  • 3.递归回溯模板
  • 4.迭代回溯模板

1.子集树

                           组合问题
                         问题是:  选?还是不选?

回溯法(01背包问题)dfs bfs 组合树排列树问题 及相应模板_第1张图片

也是一种01背包问题

#include
using namespace std;

int t,m,time[105],val[105],max_value=0;

void dfs(int num,int ct,int cv){     //num:子集树层数
	if(ct>t)
		return ;
	if(num>m){
		max_value=max(cv,max_value);
		return ;
	}
	dfs(num+1,ct+time[num],cv+val[num]);
	dfs(num+1,ct,cv);
} 

int main(){
	cin>>t>>m;
	for(int i=1;i<=m;i++)
	cin>>time[i]>>val[i];
	dfs(1,0,0);
}

2. 排列树

                                         排列问题
                                         问题是:选的方式?因为都要选。

回溯法(01背包问题)dfs bfs 组合树排列树问题 及相应模板_第2张图片

一定要用到回溯法
状态数组 :下标为数的元素,数值表示状态
例如:flag[10]=1 表示第十个元素已经选了

状态改变,回溯,构造全局变量数组;也可以不用回溯,放在递归参数里(不好)
回溯法一定要有状态的改变。深搜需要

题目:素数环:1~20个数摆成一个环,要求相邻两数之和为素数,求所有的摆法。

#include
using namespace std;


int flag[25]={0};
if_prime(int a,int b){
	int c=a+b;
	//判断a+b是不是素数
	if()
		return 1;
	else 
		return 0; 
	
} 

void dfs(int t){         //排列数的层数 
	int i;
	
	for(i=1;i<=20;i++){
		if(flag[i]==0&&is_prime(i,ans[t-1])){
			ans[t]=i;
			flag[i]=1;
			if(t==20){
				if(is_prime(ans[i],ans[20])){
					print();
				}
			}
			else
				dfs(t+1);
				flag[i]=0;           //回溯,状态回溯 
		}
	}

}


int main(){
	
	dfs(1);
} 

3.递归回溯模板

//递归回溯
void dfs(int k)
{
	int i,j,flag;
	if(k<规模)
	{
		flag=0;
		if(约束条件)
		flag=1;
		if (flag==0)
			cout<<一个解;
		else 
			dfs(k+1);
	} 
 }

4.迭代回溯模板

//迭代回溯
 int i=1;a[i]=元素初值;
 while(1)
 {
 	flag=1;
 	for(k=i-1;k>=1;k--)
 		if(约束条件)
 			flag=0;
 	if(flag==1&&边界条件)
	 cout<<一个解;
	if(i<n&&flag==1)
	{
		i++;a[i]=取值点;continue; 
	 } 
	while(a[i]==回溯点&&i>1)
		i--;
	if(a[i]==n&&i==1)
		break;
	else
	 	a[i]=a[i]+1;
  } 

你可能感兴趣的:(算法,深度优先,宽度优先,算法)