HDU 1455 Sticks
来源:互联网 发布:丁丁软件如何使用 编辑:程序博客网 时间:2024/05/20 01:12
题意:
给你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 // TESTconst 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[N];bool v[N];//记录每个长度是否被用过了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;}
0 0
- HDU 1455 Sticks
- Hdu 1455 Sticks
- hdu 1455 Sticks
- HDU 1455 Sticks
- hdu 1455 Sticks
- hdu 1455 Sticks
- HDU 1455 Sticks
- 【DFS】hdu 1455 Sticks
- Sticks hdu 1455
- hdu 1455 sticks
- HDU 1455 Sticks
- HDU 1455 Sticks
- HDU 1455 Sticks
- HDU 1455 Sticks
- day3 HDU 1455 Sticks
- hdu 1455 Sticks
- HDU 1455 Sticks
- hdu 1455 hdu 1455 Sticks
- 第五周 项目四 静态成员应用
- [刷题]Find Peak Element
- html学习笔记(1)
- JellyBean的VSync与三级buffer的入门介绍(外文翻译)
- Lucence 4.6 实例代码
- HDU 1455 Sticks
- 引用母版页后在page页面修改母版页控件的值的方法
- MyEclipse 设置@注解提示
- Java学习笔记——多态的理解
- java面试
- Postgresql 自增语句
- IntentService源码分析
- 黑马程序员——Java基础---面向对象(一)
- 常见属性