蓝桥杯-Sticks-DFS搜索

news/2024/7/7 21:14:53

题目

样例输出是

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。

代码

#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;
}

 


http://lihuaxi.xjx100.cn/news/2105706.html

相关文章

记一次由于e2fsprog升级引起文件系统挂载失败

现像&#xff1a; mount -t ext4 /dev/mmcblk0p17 /var/backups 执行时报错EXT4-fs (mmcblk0p17): Couldnt mount because of unsupported optional features (2000)&#xff1b; 要如何解决&#xff1f; 首先明确一个问题&#xff0c;文件系统特性仅与软件有关&#xff0c;…

电机学(笔记二)

负载与电流对应&#xff0c;电枢电压与转速对应。 电动机的输入功率P1 电磁功率Pm 铜损功率 Pcu 轴上输出机械功率P2 空载功率P0&#xff08;包括铁损耗&#xff0c;机械损耗和附加损耗&#xff09; 铜损耗Pcu 发电机的机械功率P1 电磁功率Pm 空载功率P0&…

代码随想录阅读笔记-字符串【翻转字符串中单词】

题目 给定一个字符串&#xff0c;逐个翻转字符串中的每个单词。 示例 1&#xff1a; 输入: "the sky is blue" 输出: "blue is sky the" 示例 2&#xff1a; 输入: " hello world! " 输出: "world! hello" 解释: 输入字符串可以在前…

Linux学习笔记-Linux学习方法

Linux建议学习路线 计算机概论与硬件相关知识&#xff1a; 因为既然想要走Linux这门路&#xff0c;信息相关的基础技能也不能没有啊&#xff01; 所以先理解一下基础的硬件知识&#xff0c;不用一定要全懂&#xff0c;又不是真的要你去组计算机&#xff0c;但是至少要“听过、有…

Springboot自动校验@NotBlank@NotNull@NotEmpty

1、依赖问题&#xff1a; 查看搭建的SpringBoot项目中 NotEmpty 是否可以引用&#xff0c;查询资料发现从SpringBoot 2.3.0之后放弃了默认对javax.validation 的支持。 <dependency> <groupId>org.springframework.boot</groupId> …

3月第2周精选#ComfyUI爱好者中文社区

社群精华周报&#xff08;3月第2周&#xff09;截止至3.17日 &#xff0c;感谢 WritterGPT ML2627 的记录。 分享者 / 奥特曼 自动将漫画转录为文字并生成剧本 Magi 模型由牛津大学工程科学系的视觉几何组开发&#xff0c;它可以全自动地为漫画页生成剧本&#xff0c;包括谁说了…

KVM安装-kvm彻底卸载-docker安装Webvirtmgr

KVM安装和使用 一、安装 检测硬件是否支持KVM需要硬件的支持,使用命令查看硬件是否支持KVM。如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的 egrep ‘(vmx|svm)’ /proc/cpuinfo关闭selinux将 /etc/sysconfig/selinux 中的 SELinux=enforcing 修改为 SELinux=d…

音视频开发之旅——音频基础概念、交叉编译原理和实践(LAME的交叉编译)(iOS)

本文主要讲解的是音频基础概念、交叉编译原理和实践&#xff08;LAME的交叉编译&#xff09;&#xff0c;是基于iOS平台&#xff0c;示例代码如下所示&#xff1a; iOSAudioDemo 另外&#xff0c;Android平台也有相关的文章&#xff0c;如下所示&#xff1a; 音视频开发之旅…