DFS 深搜专题 入门典例 -- 凌宸1642

DFS 深搜专题 入门典例 – 凌宸1642

深度优先搜索 是一种 枚举所有完整路径遍历所有情况的搜索方法 ,使用 递归 可以很好的实现 深度优先搜索。

文章目录

    • DFS 深搜专题 入门典例 -- 凌宸1642
      • 1 最大价值
      • 2 最优方案
      • 3 全排列
      • 4 组合的输出
      • 5 组合+判断素数
      • 6 N 皇后问题
      • 7 出栈序列统计
      • 8 走迷宫

1 最大价值

题目描述

​ 有 n 件物品,每件物品的重量为 w[i] , 价值为 c[i] 。现在需要选出若干件物品放入一个容器为 V 的背包中,使得在选入背包的物品重量和不超过容量 V 的前提下 ,让背包中的物品的价值之和最大,求最大价值。(1 ≤ n≤ 20 )

输入描述:

​ 第一行输入物品总数 n 和 背包容量 v 。

​ 第二行输入 n 个整数, 分别表示 n 件物品各自的重量。

​ 第三行输入 n 个整数, 分别表示 n 件物品各自的价值。

输出描述:

​ 对于每个测试用例,在一行中输出最大价值。

样例输入:

5 8
3 5 1 2 2
4 5 2 1 3

样例输出:

10
#include
using namespace std ;
#define MAX 30
int n , v , maxValue = 0 ; // 物品件数 n,背包容量 v,最大价值 maxValue 
int w[MAX] , c[MAX] ; // w[i]为每件物品的重量, c[i]每件物品的价值
// dfs ,index 表示当前处理物品的编号 , sumW sumC 分别为当前 总重量 和 总价值
void dfs(int index , int sumW , int sumC){
   
	if(index == n) {
    // 已经完成对 n 件物品的处理
		if(sumW <= v && sumC > maxValue ) maxValue = sumC ; // 如果此时最大价值符合题意,则更新
		return ;
	}
	// 岔道口 
	dfs(index + 1 , sumW , sumC) ; // 不选择第 index 件物品
	dfs(index + 1 , sumW + w[index] , sumC + c[index]) ; // 选择了第 index 件物品 
} 
int main(){
   
	cin >> n >> v ; // 输入 物品数 n 和 背包容量 v 
	for(int i = 0 ; i < n ; i ++) cin >> w[i] ; // 输入 n 件物品的 重量
	for(int i = 0 ; i < n ; i ++) cin >> c[i] ; // 输入 n 件物品的 价值
	dfs(0 , 0 , 0) ; // 调用 dfs 进行深搜
	cout << maxValue << endl ;  // 深搜结束后, maxValue 中存有最大价值,直接输出
	return 0;
}
// 对此 dfs 进行剪枝后 ,剪枝是在保证算法正确的情况下,通过题目条件限制来减少 DFS 计算量的方法
void dfs(int index , int sumW , int sumC){
   
    if(index == n) return ; //完成对 n 件物品的选择
    dfs(index + 1 , sumW , sumC) ; // 未选择第 index 件物品
    if(sumW + w[index] <= v ) {
    // 只有当选择第 index 件物品之后,容量不会超过 v ,才进行选择
        if(sumC + c[index] > maxValue)
            maxValue = sumC + c[index] ;  // 更新最大价值 maxValue
        dfs(index + 1 , sumW + w[index] , sumC + c[index]) ; // 选择第 index 件物品
	}
}

2 最优方案

题目描述:

​ 给定一个序列,枚举这个序列的所有子序列(可以不连续)。例如对序列{1,2,3}来说,他的所有子序列为{1},{2},{3},{1,2},{1,3},{1,2,3}。枚举所有子序列的目的很明显——可以从中选择一个“最优”子序列,使它的某个特征是所有子序列中最优的;如果有需要,还可以将这个最优子序列保存下来。显然,这个问题也可以等价于 枚举从 N 个整数中选择 K 个数的所有方案。

​ 给定 N 个整数(可能有负数),从中选择 K 个数,使得这 K 个数的和恰好等于给定的一个整数 X; 如果有多种方案,则选择他们当中平方和最大的一个。数据保证这样的方案唯一。例如,从 4 个整数{2,3,3,4}中选择两个数,使他们的和为 6 。显然有两种方案{2,4} 和{3,3} ,其中平方和最大的方案为{2,4}。

输入描述:

​ 第一行输入 3 个正整数 ,依次输入序列的长度 N,从中选择数的数量 K ,和恰好等于的和 X

​ 第二行输入 N 个整数(可能有负数),表示序列中的数。

输出描述:

​ 输出分两行,第一行输出 K 个数 , 表示最优序列中的元素。元素之间用空格分隔,且行末没有于的空格

​ 第二行输出 最优方案的平方和。

样例输入:

4 2 6
2 3 3 4

样例输出:

2 4
20
#include
using namespace std ;
#define MAX 100010
int n , k , x , maxSumSqu = - 1 , a[MAX] ;//分别表示,序列长度,选择数量,恰好的和,最大平方和,序列
vector<int> temp , ans ;  // temp 存放临时方案,ans 存放平方和最大的方案 
// dfs参数列表分别表示 处理第 index 个数,现在已选 nowK 个数,当前已选数字的和 sum 及其平方和 sumSqu
void dfs(int index , int nowK , int sum , int sumSqu){
   
	// 找到第 k 个数的和为 x 
	if(nowK == k && sum == x){
   
		if(sumSqu > maxSumSqu){
    // 如果比当前的更优 
			maxSumSqu = sumSqu ; // 更新最大平方和 
			ans = temp ; // 更新最优方案 
		}
		return ;
	}
	// 已经处理完 n 个数,或者超过 k 个数,或者和超过 x,返回 
	if(index == n || nowK > k || sum > x) return ; 
	// 选第 index 个数
	temp.push_back(a[index]) ;// 将第 index 个数 入栈,然候搜索下一个数,注意参数各个值的变化
	

你可能感兴趣的:(dfs,算法)