HDU 1455 DFS+剪枝

该博客介绍了一种使用深度优先搜索(DFS)解决HDU 1455问题的方法,并着重强调了剪枝优化在过程中的关键作用。博主首先将树枝按长度排序,从最长的开始搜索,当找到满足条件的最小拼凑长度时停止。在DFS过程中,通过变量记录搜索状态,并在循环中实施剪枝策略:1. 当长度为0时,直接返回,避免无效搜索;2. 跳过与当前树枝长度相同的后续树枝。文章提供了具体实现代码,展示了如何在实践中应用DFS和剪枝技巧。

思路:

DFS:

首先,将这些树枝从小到大排序,然后从最大的树枝开始搜索,到这些树枝长度总和为止,只要dfs到满足条件的最小拼凑长度就break掉

那么,在dfs里面,x参数表示从哪根树枝搜索,len表示当前的拼凑的树枝长度,hope表示期望拼凑的长度,size表示所用树枝的根数。每用一根树枝都会使size+1,终止条件为所用树枝根数和总根数相等,那么表示可以满足题意

在dfs循环内部,从前往后,如果该树枝没被用过且当前长度+该树枝长度小于等于期望长度那么进行判断,将该树枝标记为用过,分情况讨论继续往下dfs:如果刚好等于要拼凑的长度hope那么继续往下深搜,初始化参数,根数+1;否则在这个条件之上进行dfs,然后回溯。

循环下面的剪枝(这题需要剪枝优化):

1.len==0 return ;表示最开始的时候第一根树枝根本就用不了,那么这个dfs就不用进行下去了(因为你下面无论怎么dfs,这根树枝总是组成不了你想要的那个数值,所以所用树枝根数恒不等于总根数,往下没必要)。

2.while(i<n&&a[i+1]==a[i])i++; 因为if语句判断到最后是没有满足等于期望长度这个条件的,所以和它相同长度的树枝也没必要重复相同的工作,直接跳过。

具体实现代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int a[105];
int book[105];
int n;
int flag; 
bool cmp(int a,int b)
{
	return a>b;
}
void dfs(int x,int len,int hope,int size)
{
	if(flag==1)
	return ;
	
	if(size==n)
	{
		flag=1;
		return ;
	}
	
	for(int i=x;i<=n;i++)
	{
		if(book[i]==0&&a[i]+len<=hope)
		{
			book[i]=1;
			if(a[i]+len==hope)
			dfs(1,0,hope,size+1);
			
			else
			dfs(i+1,len+a[i],hope,size+1);
			//if(flag==1) return ;
			book[i]=0;
			
			if(len==0)return ;
			while(i<n&&a[i+1]==a[i])i++;	
		}
	}
	return ;
}
int main()
{
	int i,j,sum;
	while(cin>>n)
	{
		if(n==0)
		break;
		
		sum=0;
		for(int i=1;i<=n;i++)
		{
		cin>>a[i];
		sum+=a[i];
		}
		sort(a+1,a+1+n,cmp);
		
		for(int i=a[n];i<=sum;i++)
		{
			memset(book,0,sizeof(book));
			flag=0;
			if(sum%i==0)
			{
				dfs(1,0,i,0);
				if(flag==1)
				{
					cout<<i<<endl;
					break;
				}
			}
		}
			
	}
}

 

### 关于DFS剪枝和优化方法 #### DFS剪枝的概念 深度优先搜索(Depth First Search, DFS)是一种用于遍历或搜索树或图的算法。该算法尝试深入探索每一个节点直到无法继续为止,再回溯到上一个节点并重复此过程。然而,在解决实际问题时,未经优化的DFS可能会遇到状态空间爆炸的问题,导致效率低下甚至超时。 为了提升性能,可以采用剪枝技术来减少不必要的计算路径。具体来说,就是当发现当前分支不可能得到更优解时提前终止其扩展[^1]。 #### 剪枝策略的应用实例 对于给定条件下的圆柱体体积固定而表面积最小化问题,可以通过合理设置r和h之间的增长关系来进行有效剪枝。即规定每次迭代中的半径\( r_i \) 和高度 \( h_i \) 应满足严格递增的关系:\[ r(i)<r(i+1),\quad h(i)<h(i+1)\] 这种做法不仅简化了逻辑判断流程,而且有助于避免重复访问相同的状态组合,从而提高了整体求解速度。 #### C++实现示例 下面是一个简单的C++代码片段展示如何利用上述原则实施DFS剪枝: ```cpp #include <iostream> using namespace std; void dfs(int depth, int n, double &minSurfaceArea){ if (depth >= minSurfaceArea || !canFormVolume(n)) return; // 尝试不同的r,h组合... } int main(){ double minSurfaceArea = DBL_MAX; int volume = /* 输入目标体积 */; dfs(0, volume, minSurfaceArea); } ``` 在此基础上还可以进一步考虑其他形式的剪枝措施,比如基于贪心思想预先排除明显不合理的候选方案;或是引入记忆化机制防止多次处理同一组参数等[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值