poj 1011

这道题我还是用回溯法+剪枝

不过这道题必须要减的比较深才能通过。

剪纸分析:

1.总长度必须要比数据的任一都要长,

2.如果木棍要多于一个,那么该长度必须不是素数。

3.每个木棍的长度是总长度的约数。

#include <stdio.h>
#include<stdlib.h>
#include <string.h>
int st[65];
int mark[65];
int s, j, n;
int cmp(const void *a,const void *b)
{
	return *(int *)a-*(int *)b;
}
int dfs(int sum, int k, int cnt){ //sum 是正在拼的木棍已经拼出的长度, k是从哪根碎木块开始拼,cnt是正在拼第几根木棍
	if (cnt == s) //如果拼的木块数等于总长度除以所枚举的木棍长度
		return 1;
	else if (sum == j)//如果本根木块拼完,拼下一根,再次从第0根木棍开始找
		return dfs(0, 0, cnt + 1);
	else
	{
		int pre, i;
		for (pre = 0, i = k; i < n; i++)//枚举木棍
		if (mark[i] && st[i] + sum <= j) //如果这根木棍被加过,并且它不等于前一块的长度
		{
			mark[i] = 0;
			if (dfs(sum + st[i], i + 1, cnt))//从下一根木棍开始搜索
				break;
			mark[i] = 1; //如果向下搜索不成功回溯
		if (k == 0)
			return 0;//如果回溯后k==0说明这根正在被还原的这根木棍还原失败了.也就是说剩下的木棍不足以拼出原始木棍 
		}
	if (i == n)   //如果i < n 说明 搜索到成果了,若搜到 i == n-1 还未搜索到说明失败, 需要回退了 
		return 0;
	else
		return 1;
	}
}
int main()
{
	int i, sum;
	while(scanf("%d",&n), n)
	{
		for (i = sum = 0; i < n; i++)
		{
			scanf("%d",&st[i]);
			sum += st[i];
		}
		qsort(st,n, sizeof(st),cmp);//以降序序列排序,首相值为木块最大值
		for (j = st[0]; j < sum; j++) //最长的木棍的长度一定不会超过以前的木棍长度,所以从最长的长度开始枚举
			if (sum % j == 0)
			{
			s = sum / j;
			memset(mark, 1, sizeof(mark));
			if (dfs(0, 0, 0)) break;
		}
		if (j == sum)
			printf("%d",sum);
		else
			printf("%d",j);
	}
	return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值