hdu 1455 sticks(经典深搜+剪枝技巧)



题意:有一堆的木棒,长度不一,它们是有一些整齐的木棒截断而成的,求最小的木棒原始长度。

思路很简单深搜,但是直接深搜的话会tle,首先可以对木棒长度进行排序从大到小,优先使用长度长的木棒,加入当前长度不符合,考虑下一个木棒

其次如果长度为零的时候选择木棒失败,那么直接退出,实测加上这一剪枝就可以ac,这一剪枝可以帮助我们尽可能的在靠近树根处剪枝,所以优化效果很明显。

然后是如果这次选择的木棒长度和上次失败时的一样,那么剪枝。

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack> 
#include<string>
#include<map> 
#include<set>
#define eps 1e-6 
#define LL long long  
using namespace std;  

const int maxn = 70;
const int INF = 0x3f3f3f3f;
int n, sumv, target, aim;//target表示目标的棍子个数,aim表示目标的棍子长度 
int stick[maxn], vis[maxn];
bool cmp(int a, int b) {
	return a > b;
}

void init() {
	sumv = 0;
	for(int i = 0; i < n; i++) {
		cin >> stick[i]; sumv += stick[i];
	}
	sort(stick, stick+n, cmp);
}

bool dfs(int cnt, int len, int pos) {
	if(cnt == target) return true;
	if(len == aim) return dfs(cnt+1, 0, 0); 
	for(int i = pos; i < n; i++) {                         //从大到小排序后,按顺序搜索 
		if(!vis[i] && len+stick[i] <= aim) {
			vis[i] = 1;
			if(dfs(cnt, len+stick[i], i+1)) return true;
			vis[i] = 0;                                     
			if(len == 0) return false;                     //如果第一根时失败剪枝 
			while(i+1 < n && stick[i+1] == stick[i]) i++;  //如果下一根长度跟当前的失败的长度一样,剪枝 
		}
	}
	return false;
}

void solve() {
	int ans = 0;
	for(int i = 1; i <= sumv; i++) if(sumv % i == 0) {
		memset(vis, 0, sizeof(vis));
		aim = i; target = sumv / aim;
		if(dfs(0, 0, 0)) {
			ans = aim; break;
		}
	}
	cout << ans << endl;
}

int main() {
//	freopen("input.txt", "r", stdin);
	while(scanf("%d", &n) == 1 && n) {
		init();
		solve();
	}
	return 0;
}










评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值