poj1011——剪枝dfs搜索题

本文介绍了一种通过组合不同长度短棍以形成相同长度长棍的问题解决算法。该算法利用了剪枝技巧来提高效率,并通过递归深度优先搜索(DFS)策略找到可能的最短长棍长度。

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

题意:

有好多根短棍

他们可以组合成n个长度相同的长棍

求长棍的最短值


粗略参考了网上的1个剪枝技巧:排序,舍弃 之前相同长却搜失败的棍子

然后开始自己编写

发现速度超时, 对着数字推演半天,最终发现len=0,也就是搜新棍子,但是往下搜却失败,那么这根棍子将不存在,这是不可能的,所以直接要直接跳回上级

明天开始回顾图论,看看华为的那个参赛题到底难不难微笑

#include<stdio.h>
#include<string.h>
#include<math.h>
#define M 2000

int flag[M],stick[M];
int stick_n,want_len,ans_flag,bad_flag;
void dfs(int n,int len)
{
	int i,change_flag=1;
	if(ans_flag==1) //如果已经发现答案,则退出
		return ;
	if(len>want_len) //如果len比假设棍长 大,则退出
		return ;
	if(len==want_len)  //如果等于假设棍长,则看n
	{
		if(n==stick_n)  //相等,说明找到答案
		{
			ans_flag=1;
		}
		else
			len=0; //否则,说明已经找到一组假设棍长组合,len重置0.往下继续找
	}

	for(i=0;i<stick_n&&ans_flag!=1&&bad_flag!=1;i++)
	{
		if(i!=0&&stick[i]==stick[i-1])  //如果之前与自己相同的棍子往下搜时都没找到,则跳过
		{
			if(change_flag==0)
				continue;
		}
		else change_flag=1;

		if(flag[i]==1)  //如果棍子已被选择过,则跳过
			continue;
		flag[i]=1;//选择此棍
		dfs(n+1,len+stick[i]); //往下搜
		change_flag=0; //说明这个棍子没找到,那么与他相同的棍子往下搜肯定也失败
		flag[i]=0; //取消此棍选择
		if(len==0)  //如果这个棍子是新棍的第一个,dfs失败,那么后面此棍将不存在,这样不合理
					//故跳过之后所有棍子的搜索
		{
			break;
		}
	}
}
void sort()
{
	int i,j,temp;
	for(i=0;i<stick_n;i++)
		for(j=i;j<stick_n;j++)
		{
			if(stick[i]<stick[j])
			{
				temp=stick[i];
				stick[i]=stick[j];
				stick[j]=temp;
			}
		}
}

void main()
{
	int sum,i,max;
	while(scanf("%d",&stick_n),stick_n!=0)
	{
		sum=0;
		for(i=0;i<stick_n;i++)
		{
			scanf("%d",&stick[i]);
			sum+=stick[i];
			flag[i]=0;
		}
		sort();		//排序,从大到小
		max=stick[0];  //原棍长应该在max到sum之间
		ans_flag=0;
		for(i=max;i<=sum;i++)
		{
			if(sum%i!=0) //如果假设原棍长不被sum整除,则舍弃
				continue;
			want_len=i; //假设原棍长
			dfs(0,0);
			if(ans_flag==1) //发现答案,则输出
			{
				printf("%d\n",i);
				break;
			}
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值