HDU 1455 Sticks
2015-04-12 17:59
375 查看
题意:
给你n个不超过50的长度,它们是一根或多跟棍子(长度都相同)的一部分,求符合条件的棍子的最短长度。
思路:
这道题里面分组的思路真是经典,剪枝的思路也是很有趣。
首先从这些长度里面的最大的长度开始遍历(因为棍子的长度肯定不小于最大的长度),看这个长度的棍子是否能被组成。
至于具体剪枝看代码里面的注释吧。
Code:
给你n个不超过50的长度,它们是一根或多跟棍子(长度都相同)的一部分,求符合条件的棍子的最短长度。
思路:
这道题里面分组的思路真是经典,剪枝的思路也是很有趣。
首先从这些长度里面的最大的长度开始遍历(因为棍子的长度肯定不小于最大的长度),看这个长度的棍子是否能被组成。
至于具体剪枝看代码里面的注释吧。
Code:
#include<cstring> #include<cstdlib> #include<cstdio> #include<cctype> #include<cmath> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<bitset> #include<queue> #include<stack> #include<list> #include<map> #include<set> #define TEST #define Mt(f, x) memset(f, x, sizeof(f)); #define LL long long #define rep(i, s, e) for(int i = (s); i <= (e); ++i) #ifdef TEST #define See(a) cout << #a << " = " << a << endl; #define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl; #define debug(a, s, e) rep(_i, s, e) {cout << a[_i] << ' ';} cout << endl; #define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee);} #else #define See(a) #define See2(a, b) #define debug(a, s, e) #define debug(a, s, e, ss, ee) #endif // TEST const int MAX = 2e9; const int MIN = -2e9; const double eps = 1e-8; const double pi = acos(-1.0); using namespace std; const int N = 75; int a ; bool v ;//记录每个长度是否被用过了 int n; bool dfs(int t, int add, int sum, int tsum)//t代表上次搜索的长度的编号,add已经累积的长度,sum要组成棍子的长度,tsum剩余需要组成的长度 { if(sum == tsum)//剩余的长度等于要找的长度,那么就已经找到了 { return true; } if(add == sum)//如果已经累积的长度等于要找的长度,就直接再从头找下一根棍子 { return dfs(-1, 0, sum, tsum - sum); } for(int i = t + 1; i < n; ++i) { if(v[i])//如果用过了,就用下一个 { continue; } if((sum - add) / a[i] > n - t)//由于我们对长度已经排过序了,所以长度必定是不递减的,如果以后的都是当前长度的,还组不成一根棍子,就返回false { return false; } if(add + a[i] <= sum)//如果累积的和此根棍子和小于等于要组成的棍子长度 { v[i] = true;//记录用过了 if(dfs(i, add + a[i], sum, tsum))//如果找到了返回true { return true; } v[i] = false; if(add + a[i] < sum && add == 0)//如果这个长度组不成一根棍子,并且以前没有累积的数值,就说明以后只要包含这根棍子的组合都不符合,那就可以直接返回false return false; if(add + a[i] == sum)//如果这个长度组成棍子不成功,那么剩下和它一样长度的也组不成棍子 { while(a[i] == a[i + 1]) i++; } } } return false; } int main() { while(~scanf("%d", &n) && n) { int tsum = 0; for(int i = 0; i < n; ++i) { scanf("%d", &a[i]); tsum += a[i]; } sort(a, a + n, greater<int>()); //根据长度从大到小排序,以后就可以方便的剪枝 for(int i = a[0]; i <= tsum; ++i) //从最长的开始遍历,到他们的总和 { if(tsum % i == 0) //如果总长度能被这个长度整除,那么有可能符合条件,因为棍子的长度都是相同的 { Mt(v, false); if(dfs(-1, 0, i, tsum)) { printf("%d\n", i); break; } } } } return 0; }
相关文章推荐
- hdu1455 Sticks(搜索+剪枝+剪枝+.....+剪枝)
- HDU 1455 Sticks
- HDU 1455 Sticks(DFS,剪枝,原来木棒的至少长度)
- HDU 1455 POJ 1011 UVA 307 Sticks
- HDU 1455 Sticks(dfs+强剪枝)
- HDU 1455 Sticks(DFS+剪枝)
- hdu 1455 Sticks(经典搜索)
- hdu 1455 Sticks
- HDU 1455 Sticks
- HDU 1455 Sticks
- hdu 1455 Sticks
- hdu 1455 poj 1011 sticks
- hdu 1455 Sticks(DFS+剪枝)
- HDU - 1455 Sticks(深搜+剪枝)
- HDU 1455 Sticks
- HDU 1455 Sticks
- HDU 1455 Sticks 解题报告
- HDU-1455 Sticks 经典dfs剪枝
- uva 215 hdu 1455 uvalive5522 poj 1011 sticks
- hdu 1455 sticks