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;
}
时间: 2024-10-09 19:11:57

hdu 1455 sticks(经典深搜+剪枝技巧)的相关文章

hdu 1518 Square(深搜+剪枝)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1518 题目大意:根据题目所给的几条边,来判断是否能构成正方形,一个很好的深搜应用,注意剪枝,以防超时! 1 #include <iostream> 2 #include <cstdio> 3 #include<algorithm> 4 #include <cstring> 5 using namespace std; 6 int ap[30],visit[30]

NYOJ 293 Sticks 【深搜】+【剪枝】

这是一道让人泪奔的题,它深刻的说明了什么是剪枝,哪怕是再小的一个细节,一旦递归规模增大都会引发巨大的时间消耗,真是神题~ Sticks 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the

poj1011(深搜+剪枝)

题意:给m根木棍,将它们重新拼成n根一样长的木棍,并使得n尽量大(即每个新木棍尽量短). 解法:经典的搜索题目.从小到大枚举拼成的新木棍长度,每次枚举进行一次深搜.这题关键是如何剪枝. 1.当枚举的长度不能整除总长度的时候,剪枝:(这个很显然) 2.先将木棍从长到短排序,枚举时先尝试长的木棍.(先枚举长的可以使得搜索深度不至于过深) 3.深搜时,不要企图通过换掉一个新木棍的第一根来改变失败的局面(换掉第一根A,那么A也会在以后的新木棍中被使用,但是已经证明了A无法拼成了,所以不必再尝试下去了)

hdu 1518 Square(深搜dfs)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1518 --------------------------------------------------------------------------------------------------------------------------------------------

HDU 1455——Sticks(神棍)

这题跟 HDU1518差不多 附上测试数据~~ 64 40 40 30 35 35 26 15 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40 40 25 39 46 40 10 4 40 40 37 18 17 16 15 40 40 40 40 40 40 40 40 46 40 37 32 10 47 4 42 56 61 23 5

UVA1374 - Power Calculus(迭代深搜+剪枝)

题目链接 题意:给出x和正整数n,问最少需要几次乘除法 可以得到n = x^m 思路:其实是关于指数的操作,即从1到m最少的步数.我们可以先确定最少步数m,然后进行迭代,迭代的过程也就是判断通过相加减所得到的数可以在m次操作中等于n,如果符合,m即为最小步数,如果不符合,m++,进行下一次迭代.迭代过程中要注意剪枝,即剩余的次数如果每次都是取最大值相加还是比n小的话,就直接跳出. 代码: #include <iostream> #include <cstdio> #include

hdu 1175 连连看 (深搜)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1175 题目大意:如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子)这样的两个棋子可以消掉.还有一个要注意的地方的就是转弯.转弯的次数不超过两次,这两个棋子才可以在棋盘上消去~ 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int

hdu 1010 Tempter of the Bone 深搜+剪枝

题意:在一个坐标内,给定起点和终点,问能否恰好在t时刻到达终点. 以前很少写搜索题,所以看到这个题,就按照普通的深搜写了一下,交上去超时了.后来在网上搜了一下才知道,要剪枝才行.可是,我以前从没写过剪枝,不知道怎么剪,就按照别人的思路往下想.看懂以后,我对剪枝的理解是:对于一些没有必要继续搜索的路径,不再往下深搜,提前返回到上一层.花了半天时间调试代码,终于AC了. 奇偶剪枝:根据题目,doggie必须在第t秒到达门口.也就是需要走t-1步.设doggie开始的位置为(sx,sy),目标位置为(

hdu1518(Square)深搜+剪枝

点击打开杭电1518 Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-end to form a square? Input The first line of input contains N, the number of test cases. Each test case begins with an integer 4 <= M <= 20,