回溯 and 深度优先搜索(DFS)
1.什么是深度优化搜索
DFS 全称是 Depth First Search,中文名是深度优先搜索,是一种用于遍历或搜索树或图的算法。所谓深度优先,就是说每次都尝试向更深的节点走。DFS 最显著的特征在于其 递归调用自身。同时与 BFS 类似,DFS 会对其访问过的点打上访问标记,在遍历图时跳过已打过标记的点,以确保 每个点仅访问一次。符合以上两条规则的函数,便是广义上的 DFS。
马基佬跟我们讲的深度优先搜索:

其实就是暴枚嘛。。。
2.基本框架
void dfs(int dep,参数表){//dep:搜索程度
自定义参数;
if(当前是目标状态){
输出解或作计数,评价处理;
}else{
for(int i=1;i<=状态的拓展可行数;i++){
if(第i种状态扩展可行){
维护自定义参数;
dfs(dep+1,参数表);
}
}
}
}
3.举个例子
V题--------体积
题目描述
给出 n 件物品,每件物品有一个体积 V[i],求从中取出若干件物品能够组成的不同的体积和有多少种可能。至少选择1件物品
输入格式
第 1 行 1 个正整数,表示 n.
第 2 行 n 个正整数,表示 Vi,每两个数之间用一个空格隔开.
输出格式
一行一个数,表示不同的体积和有多少种可能.
样例
样例输入
3
1 3 4
样例输出
6
数据范围与提示
对于 30% 的数据满足:n≤5,Vi≤10
对于 60% 的数据满足:n≤10,Vi≤20
对于 100% 的数据满足:n≤20,1≤Vi≤50
题解
#include<iostream>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
int n,v[1005];
int ans;
bool flag[1005];
void dfs(int dep,int k){
if(dep==n+1){
if(flag[k]==0){
ans++;
flag[k]=1;
}
return;
}
dfs(dep+1,k+v[dep]);
dfs(dep+1,k);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>v[i];
}
dfs(1,0);
cout<<ans-1;
return 0;
}
4.回溯法
概念:回溯法是一种经常被用在深度深度优先搜索(DFS)和广度优先搜索(BFS)的技巧,其本质是:走不通就回头。
马基佬跟我们讲的回溯法(带框架):


例子
就拿A题说说吧--------组合的输出
题目描述
排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,n,从中任取r个数,现要求你用递归的方法输出所有组合.
例如n=5,r=3,所有组合为:
1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5
输入格式
一行:两个正整数 n 和 r (r10)
输出格式
字典序从小到大的全排列及全排列的总个数.
样例
样例输入
3 2
样例输出
1 2
1 3
2 1
2 3
3 1
3 2
6
题解
#include<iostream>
#include<cstdio>
#include<stack>
#include<queue>
#include<algorithm>
#define inout ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
int n,r;
int a[15];
int b[15];
int x;
int ans;
void dfs(int dep){
if(dep==r+1){
ans++;
for(int i=1;i<=r;i++){
printf("%d ",a[i]);
}
printf("\n");
return;
}else{
for(int i=1;i<=n;i++){
if(!b[i]){
b[i]++;
a[dep]=i;
dfs(dep+1);
b[i]--;
}
}
}
}
int main(){
inout;
scanf("%d %d",&n,&r);
dfs(1);
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号