1 条题解
-
0
解题思路
当石子堆数达到堆时,传统动态规划所需的数组会导致空间和时间复杂度过高,此时 GarsiaWachs 算法成为更优选择。
该算法从第一个石堆开始找符合的石堆k,然后合并与堆,再向前找j堆石子,满足,插入到石堆的后面,之后重新寻找符合条件的位置重复操作。
算法的核心想法在于:将石子视为三堆,若,先合并与k堆是合理的。合并后将新堆插入到后面(其中是第一个大于新堆重量的前趋堆),本质是将与视为整体,形成、、新堆的结构。由于新堆重量小于,后续会优先合并与新堆,通过这种局部最优决策的迭代,最终可得到全局最优的归并结果。
标程
#include <cstdio> #include <cstring> #include <climits> #include <algorithm> using namespace std; const int MAXN = 55555; const int INF = 1 << 30; struct ARC { int last; int next; int data; void init() { next = last = 0; data = INF; } }; ARC arc[MAXN]; void in(int& cnt) { arc[cnt].next = cnt + 1; arc[cnt + 1].last = cnt; scanf("%d", &arc[++cnt].data); } void del(int u) { arc[arc[u].last].next = arc[u].next; arc[arc[arc[u].last].next].last = arc[u].last; } void reinsert(int x, int u) { for (int i = arc[u].last; ; i = arc[i].last) { if (arc[i].data > x) { arc[u].last = i; arc[u].data = x; arc[u].next = arc[i].next; arc[arc[u].next].last = u; arc[i].next = u; return; } } } void work(int n) { int ans = 0; int cnt = 0; for (int i = 0; i <= n + 1; i++) { arc[i].init(); } for (int i = 1; i <= n; i++) { in(cnt); } for (int i = 1; i < n; i++) { for (int j = arc[0].next; j; j = arc[j].next) { int l = arc[j].last; int r = arc[j].next; if (arc[l].data <= arc[r].data) { del(l); del(j); int weight = arc[l].data + arc[j].data; ans += weight; reinsert(weight, j); break; } } } printf("%d\n", ans); return; } int main() { int n; while (scanf("%d", &n) != EOF && n) { work(n); } return 0; }
- 1
信息
- ID
- 739
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者