P1120 小木棍(写给dfs小佬)

本文讨论了解决洛谷P1120小木棍问题的DFS方法,强调了从大到小枚举原木长度的策略以及如何利用剪枝优化算法,以减少搜索时间和空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小木棍

传送门:

P1120 小木棍 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路

看到数据范围一般来说就是用dfs了,同时肯定是需要剪枝的

先看DFS思路吧

无非两种思路:

  1. 枚举原木长度 凑相同长的原木来找可以凑多少根原木,原木数越大,单根原木长度越短(这里称原来没被锯断的木头为原木)

  2. 枚举原木长度 计算出每次如果有解的话原木数量为多少,然后凑原木数

    两者虽然都最后与原木数息息相关,但是思路1存在诸多问题,比如什么时候是dfs的终止情况,什么时候应该回溯,这里如果我们枚举的时候从小到大枚举,不依靠原木数是可以以当前每一个木头都被用来组成原木而作为dfs终止条件的,但是带来的问题是这样做的话剪枝所带来的时间优化很少,我暂时是没想到的,而且判断种植的时间复杂度也高,显然是不合理的

    第一点是刚刚看到这道题所想的,但是再转念一想很蠢!很蠢!很蠢!

    第二点的优势就在于用类似于组合数的爆搜来做十分好懂,如果不卡常不看剪枝这道题就是普及-!

ok!开搜

//rep(i,a,b)==for(int i = a; i <=b; i++)	
	rep(i,a[1],sum){
   //这边先对a数组做一个从大到小的排序,这样原木的最小长度至少也是这里木棍的最大长度,那么原木最大长度毋庸置疑是这里所有木棍之和。
	//为什么?为什么先想着,这个点的思路下面AC Code里写了
		if(sum%i==0){
   //枚举i,如果正好有sum/i根原木这时候就是有可能有解。
			cnt=sum/i;//如果有解,那么原木就有sum/i根(这边枚举的是原木长度i)
			dfs(1,0,1,i);//开搜
		}
	}
	void dfs(int x,int cur,int start,int len){
   
	//x表示当前木头组成len的第几根,cur表示但当前已组成的木棍,start表示从第几根木棍开始,len就表示当前情况下的单根原木长度
	//len表示当前单根原木长度
	if(x>cnt){
   //已找到可以组成的原木数>理想状况下的原木数就是终止条件
		cout<<len;//输出len,因为len是从小到大开始循环的所以能找到的话就是答案
		exit(0);//退出整个程序
		//exit(0)和return 的区别:exit(0)直接退出整个程序,return 是终止当前函数
		//这里找到答案就直接退出整个程序就行了,不用再return回溯浪费时间,这里也算一种剪枝
	}
	if(cur==len){
   //已组成了一根原木,我们开始组成下一根,
		dfs(x+1,0,1
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值