【TOJ 3403】Treasure Division 【双向搜索】
2014-08-13 09:43
162 查看
题意:给出n个数字,(n <= 30)将其分成两份,两份的数字数量差不超过1个,求这个两份数字之和的差最小。每个数字都是整数范围内。
思路:n<= 30很明显就是一个双向搜索的题,先将n分成两份,对于其中一份枚举所有情况,那就是2^15,然后对于后半份在枚举所有情况,然后通过二分将两个合起来即可。从而更新答案。
思路:n<= 30很明显就是一个双向搜索的题,先将n分成两份,对于其中一份枚举所有情况,那就是2^15,然后对于后半份在枚举所有情况,然后通过二分将两个合起来即可。从而更新答案。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; ll val[33], sum, ans; struct R{ ll v; int c; bool operator<(const R a)const { if (c == a.c) return v < a.v; return c < a.c; } }ran[40100]; ll f(ll a) {return a>0?a:-a;} int find(int l, int r, ll k, ll tm) { if (l == -1 || r == -1) return -1; int mid, tl, tr; tl = l, tr = r; while (l < r) { mid = l+r>>1; if (ran[mid].v < k) l = mid+1; else r = mid; } ans = min(ans, f(sum-2*(ran[l].v+tm))); if (l > tl) ans = min(ans, f(sum-2*(ran[l-1].v+tm))); if (l < tr) ans = min(ans, f(sum-2*(ran[l+1].v+tm))); } int l[33], r[33]; int main() { int n, i, j, m; while (~scanf("%d", &n)) { sum = 0; for (i = 0;i < n;i++) { scanf("%lld", &val[i]); sum += val[i]; } int st = (1<<(n/2)), c; m = 0; for (i = 0;i < st;i++) { ll tm = 0; c = 0; for (j = 0;j < n/2;j++) { if (i&(1<<j)) tm += val[j], c++; } ran[m].v = tm, ran[m++].c = c; } sort(ran, ran+m); memset(l, -1, sizeof(l)); memset(r, -1, sizeof(r)); for (i = 0;i < m;i++) { if (i == 0 || ran[i].c != ran[i-1].c) { l[ran[i].c] = i; } if (i == m-1 || ran[i].c != ran[i+1].c) { r[ran[i].c] = i; } } ans = sum; st = (1<<(n-n/2)); for (i = 0;i < st;i++) { ll tm = 0; c = 0; for (j = n/2;j < n;j++) { if (i&(1<<(j-n/2))) tm += val[j], c++; } if (c > n/2+1) continue; if (n&1) { if (c > n/2) { ans = min(ans, f(sum-2*tm)); continue; } j = find(l[n/2-c], r[n/2-c], sum/2-tm, tm); j = find(l[n/2-c+1], r[n/2-c+1], sum/2-tm, tm); }else { if (c > n/2) continue; j = find(l[n/2-c], r[n/2-c], sum/2-tm, tm); } } printf("%lld\n", ans); } }
相关文章推荐
- CodeForces-920E Connected Components? 广度搜索 双向链表 判断联通 大量重复节点的删除
- 折半枚举(双向搜索)挑战程序设计竞赛
- poj 2785 双向搜索+哈希
- 剑指offer 编程题(25):二叉树搜索与双向链表
- 162_超大背包问题 (双向搜索)
- 数据结构 将搜索二叉树转换成双向链表
- 将一颗搜索树转换成一个排序的双向链表。要求不能创建任何新的节点
- hdu 1151 - > 双向路径搜索解决覆盖问题
- hdu 6171---Admiral(双向搜索)
- HDU1401 Solitaire 双向搜索
- 2016 UESTC Traing Search Algorithm &String Problem N 简单的双向搜索
- 【NOIP2002提高组T2】字串变换-双向BFS或迭代加深搜索
- TOJ 2470Robot in Maze (广度搜索应用)
- Poj1198/HDU1401(双向搜索)
- uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)
- 8数码问题-搜索-双向BFS/A*算法
- hdu 1151 - > 双向路径搜索解决覆盖问题
- hdu6171 双向搜索+hash
- 链表问题---将搜索二叉树转换成双向链表
- 折半枚举(双向搜索)