蓝桥杯-Sticks-DFS搜索

题目

样例输出是

cpp 复制代码
6
5

题目中给错了,不知道什么时候会改。

思路

--剪枝,否则时间复杂度和空间复杂度过大,会超时。

--注意有多组测试样例时,需要将bool数组重新赋值为false。

--函数类型不是void,return语句不能省略!

--思路:刚开始想的大方向是对的,将需要处理的数组排序,然后从最大值到总和这个范围内搜索,找满足题意的木棍长度,但是剪枝这里是一头雾水。剪枝是利用一些条件使得不需要dfs许多重复的情况,已经pass掉的就不需要再递归了。看到这一题,很容易联想到粘木棍,将n个短木棍粘成m个长木棍,所不同的是,这里的m个长木棍长度都是相同的。我们可以一根一根来粘,粘成一根长木棍再粘下一根。那么就需要让此时的长木棍的长度作为参数在递归中传递。这时有三种情况,当前长度cur加上选中的短木棍的长度,可能等于、大于、小于目标长度l。(1)如果等于l,开始粘下一根长木棍,长木棍的根数要+1,cur设为0,验证接下来能不能递归成功,如果成功就可以直接返回,如果不成功就返回false,提前结束递归。验证接下来能不能递归成功,就是为了在不成功的情况下提前结束递归。(2)如果大于l,说明选中的短木棍不合适,需要继续循环遍历下一个短木棍。没有必要验证了,因为肯定会返回false的。(3)如果小于l,说明还没有粘完,还需要继续粘,也要继续循环遍历下一个短木棍。判断接下来能不能递归成功,如果不成功的话,并且cur为0,返回false。为什么只有在cur为0的时候才返回?因为如果当前长度不为0,并且拼接接下来的短木棍仍然不成功,说明此时选择的短木棍不对,需要继续for循环选择下一个合适的短木棍;如果当前长度为0,但不成功,说明在以后的递归中也不可能成功了,就直接false。

代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;

int n; //短木棍的个数 
int l; //长木棍的长度 
int num; //长木棍的个数 
vector<int> v(65);
bool b[65] = {false}; 

bool dfs(int s, int j, int cur){ //遍历小木棍的起始位置,拼成的长木棍数目,长木棍当前长度 
	if (j == num){
		return true;
	}
	
	for (int i = s; i < n; i++){
		if (b[i] == true || (i != 0 && v[i] == v[i - 1] && b[i - 1] == false)){
			continue;
		} //如果这根木棍已被访问过 或 和上一根没有被访问过的木棍长度相同,剪枝。
		 
		if (cur + v[i] == l){
			b[i] = true;
			if (dfs(0, j + 1, 0)){
				return true;
			} //如果继续深度递归能成功,直接返回。 
			b[i] = false;
			return false; //如果不能成功,提前终止。 
		}
		
		if (cur + v[i] < l){
			b[i] = true;
			if (dfs(i + 1, j, cur + v[i])){ //i + 1,不是s + 1! 
				return true;
			} //如果继续深度递归能成功,直接返回。 
			b[i] = false; 
			if (cur == 0){
				return false;
			} //不能成功,如果当前长度为0,说明还没有开始拼接 或 已经拼接成了几根,上面的if已经尝试过所有的v[i]了,所以不可能成功。如果当前长度不为0,还可以尝试接下来的v[i]。 
		} 
		//如果cur + v[i] > l,那么就需要换下一个v[i]来尝试。 
	}
	
	return false; //不是void类型的,不能省略return语句。 
}

int main(){
	while (cin >> n && n != 0){
		int sum = 0;
		for (int i = 0; i < n; i++){
			cin >> v[i];
			sum += v[i];
		}
		sort(v.begin(), v.begin() + n, greater<int>()); //从大到小深度搜索,比较好找。
		for (int i = v[0]; i <= sum; i++){
			if (sum % i == 0){
				memset(b, 0, sizeof(b)); //问题出在这里!需要将b数组重置为false,因为有多组测试用例! 
				l = i;
				num = sum / l;
				if (dfs(0, 0, 0)){
					cout << l << endl;
					break;
				}
			} 
		}
	}
	
	return 0;
}
相关推荐
hong1616887 分钟前
VSCode中配置C/C++环境
c语言·c++·vscode
小羊在奋斗21 分钟前
【C++】探秘二叉搜索树
c++·人工智能·神经网络·机器学习
爱数模的小云38 分钟前
【华为杯】2024华为杯数模研赛E题 解题思路
算法·华为
白葵新41 分钟前
PCL addLine可视化K近邻
c++·人工智能·算法·计算机视觉·3d
seanli10081 小时前
线性dp 总结&详解
算法·动态规划
小丁爱养花1 小时前
记忆化搜索专题——算法简介&力扣实战应用
java·开发语言·算法·leetcode·深度优先
Faris_yzf1 小时前
物联网LoRa定位技术详解
科技·算法
Crossoads1 小时前
【数据结构】排序算法---快速排序
c语言·开发语言·数据结构·算法·排序算法
DS数模1 小时前
2024华为杯研赛E题保姆级教程思路分析
算法·数学建模·华为·华为杯数学建模·2024华为杯·2024研赛
眰恦3741 小时前
数据结构--第五章树与二叉树
数据结构·算法