[UVA 307] Sticks (DFS回溯 + 剪枝)
来源:互联网 发布:淘宝网严禁出售黄赌毒 编辑:程序博客网 时间:2024/05/03 20:38
Sticks
题目链接:
http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=17446
题目大意:
有n根小木棍,长短不一,现在要求你将它们拼成一些长度一样的木棒,问拼成多少长度的木棒,可以得到最多的木棒数。
如样例:
95 2 1 5 2 1 5 2 1输出:6
解题思路:
这道题目很容易想到DFS回溯,关键是剪枝
有如下几个剪枝
1.把所有木棍的长度从大到小排列,组合木棒时优先使用长的木棍,这样可以加快组合速度,并且对后面的剪枝有帮助。
2.木棒的长度一定是大于等于最长木棍的长度并且小于等于所有木棍长度的和,这个很容易证明。
3.木棒的长度一定是所有木棍长度的和的约数,这个也很容易证明。
4.在某一个木棒的组合过程中,对于当前的木棍stick[i],如果stick[i-1]没有被组合并且stick[i] == stick[i-1],那么不用考虑stick[i],因为之前已经试过stick[i-1], 发现无法组合,所以stick[i]肯定更加不行。
5.如果此次是在尝试第i个木棒的第一段,假设stick[j]为当前可以被使用的最长的木棍,如果此次组合失败,直接退出搜索,退回到对第i-1个木棒的搜索。因为当stick[j]作为第i根木棒的第一段无法组合的话,作为第i + k (k > 0)的木棒的第一段也不行,因为此时所剩下的木棒更少,为其子集。
6.如果能用一段完成一根木棒,就没必要采用多段来组合,因为永远可以用多段来替代一段,却不能用一段来替代多段。
这道题目的剪枝很经典,是道好题目。
#include<iostream>#include<fstream>#include<cstdio>#include<cstring>#include<cmath>#include<map>#include<queue>#include<stack>#include<vector>#include<set>#include<ctype.h>#include<algorithm>#include<string>#define PI acos(-1.0)#define maxn 1000#define INF 1<<25#define mem(a, b) memset(a, b, sizeof(a))typedef long long ll;using namespace std;int n, a[100], sum, mx, vis[100];bool cmp(int s, int v){ return s > v;} // (1)bool dfs(int pos, int tot, int cnt){ int i; if (cnt == mx) return true; // 组合成功 for (i = pos; i < n; i++) if (!vis[i]) { if (i && !vis[i - 1] && a[i] == a[i - 1]) continue; // (4) if (tot + a[i] < sum / mx) { vis[i] = 1; if (dfs(i + 1, tot + a[i], cnt)) return true; vis[i] = 0; if (tot == 0) return false; // (5) } else if (tot + a[i] == sum / mx) { vis[i] = 1; if (dfs(0, 0, cnt + 1)) return true; vis[i] = 0; return false; // (6) } } return false;}int main (){ int i, j; while(scanf("%d", &n) != EOF) { if (!n) break; sum = mx = 0; for (i = 0; i < n; i++) { scanf("%d", a + i); sum += a[i]; if (a[i] > mx) mx = a[i]; } sort(a, a + n, cmp); mx = sum / mx; while(mx) { if (sum % mx == 0) (3) { mem(vis, 0); if (dfs(0, 0, 0)) break; } mx--; } printf("%d\n", sum / mx); } return 0;}
0 0
- [UVA 307] Sticks (DFS回溯 + 剪枝)
- UVA - 307 Sticks(回溯+剪枝)
- uva 307 Sticks(回溯剪枝)
- UVA - 307 Sticks 剪枝+回溯
- uva 307 Sticks(DFS+ 剪枝)
- uva:307 - Sticks(dfs + 剪枝)
- UVa 307:Sticks(DFS+剪枝)
- POJ 1011 Sticks(DFS回溯剪枝)
- 307Sticks(*****)经典DFS+剪枝
- UVa 307 - Sticks(暴力+剪枝)
- UVA-307 Sticks (搜索剪枝)
- [UVA 10160] Servicing Stations (DFS回溯 + 剪枝)
- Sticks(DFS+剪枝+贪心)
- Sticks (dfs经典剪枝)
- UVa 140 Bandwidth(DFS 回溯 剪枝)
- [回溯&&剪枝]Sticks UVA307
- UVA 307Sticks(dfs搜索)
- poj 1011 sticks (dfs+剪枝)
- notepad++设置
- coco2d-x 学习笔记 1 关于CCButton在单点触摸下的无法实现
- C语言求得最大公约数和最小公倍数
- 在Android中使用NDK调用OpenGl
- Looper
- [UVA 307] Sticks (DFS回溯 + 剪枝)
- 无法找到表单域***
- Java编程中“为了性能”需做的26件事
- Android 重要包的描述
- linux下find命令详解
- 【转】 Mac环境下Android APK包反编译详解
- 进军安卓,希望自己能坚持
- android:inputType参数类型说明
- OpenGL中几种变换含义