试题 算法训练 Sticks(dfs+剪枝)

在这里插入图片描述
思路:dfs+剪枝算法
1)要确定好target,也就是um of sticks的约数且要大于最大的木棍
2)木棍排序,从大到小排
3)在满足一个target的任务中,因为顺序排列,所以重复元素,前面没选的,这一次也不选,剪枝
4)在满足一个target的任务中,如果当前最长的木棍满足失败,则整条枝失败,因为我们从小到大排列,会越来越小

#include<bits/stdc++.h>
using namespace std;
#define ul unsigned long 
#define ll long long 
int q[65];
int flag;///标记 
int minn; ///符合条件的最小的木棒 
int vis[65]; ///标记一下是否用过该木棒 
int n;  
int cmp(int a,int b)  
{
	return a>b;
}
///将和minn相同长度的拼接木棒放在一个格子里面 
void dfs(int deep,int len,int num)  /// 已经放的格子数,目前所拼接木棒的长度, 当前正在选择的小棒的序号 
{
	if(flag) 
	{
		return ;
	}
	if(len==0)//len == 0说明前面都已经完成,开始新的一轮
	{
		int i=1;
		while(vis[i])
		{
			i++;
		}
		vis[i]=1;
		dfs(deep+1,len+q[i],i+1);
		 
		if(flag)
		{
				return;
		}
		vis[i]=0;//目前最长棍都失败,不用继续,直接退出,失败。
		return;
	}
	if(len==minn)
	{
		if(deep==n)//格子填完,表示所有木棍被选,成功
		{
			flag=1;
		}
		else 
		{
			dfs(deep,0,1);//还未填完,开始新的一轮
			if(flag)
			{
				return;
			}
		}
		return ;
	}
	for(int i=num;i<=n;i++)//不是新开始,也不是刚好结束,那就是要找棍子
	{
		if(vis[i]==0&&q[i]+len<=minn)
		{
			if(vis[i-1]==0&&q[i]==q[i-1])//上一根一样长且没被选过,那这一根也没必要
			{
				continue;
			}
			vis[i]=1;
			dfs(deep+1,len+q[i],i+1);
			if(flag)
			{
				return;
			}
			vis[i]=0;//失败,放下棍子
			if(len+q[i]==minn) return ;//满足了,但是前面验证过失败了,所以直接返回
			if(flag)
			{
				return;
			}
		}
	}
	if(flag)
	{
		return;
	}
}
int main()
{
	
	while(~scanf("%d",&n)&&n)
	{
		int sum=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&q[i]);
			sum+=q[i];
		}
		sort(q+1,q+1+n,cmp);
		for(int i=q[1];i<=sum;i++)
		{
			if(sum%i!=0)
			{
				continue; 
			}
			flag=0;
			memset(vis,0,sizeof(vis));
			minn=i;
			dfs(0,0,1); 
			if(flag)
			{
				printf("%d\n",i);
			  break;	
			}
			
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值