GarsiaWachs算法

对于一列的石子归并问题,除了朴素的O(n^3)的dp做法及其O(n^2)优化,还有GarsiaWachs算法。

算法流程是,找一个最小的k,使得a[k-1]<=a[k+1],将a[k-1]和a[k]合并;从当前位置向前找到一个最大的i,使得a[i]>a[k-1]+a[k],并将新合并的一堆移到i的后面;重复操作n-1次,直至只剩下1堆,答案就是每次合并结果累加起来。

 1 #include <cstdio>
 2 
 3 const int maxn = 105, inf = 0x3f3f3f3f;
 4 
 5 struct Node {
 6     int num, pre, next;
 7 } a[maxn];
 8 
 9 inline void del(int x) {
10     int pp = a[a[x].pre].pre, nn = a[x].next;
11     a[pp].next = nn, a[nn].pre = pp;
12 }
13 
14 inline void insert(int x, int y) {
15     a[x].pre = y, a[x].next = a[y].next;
16     a[a[y].next].pre = x, a[y].next = x;
17 }
18 
19 int main() {
20     int n, ans = 0;
21     scanf("%d", &n);
22     a[0].num = a[n + 1].num = inf;
23     a[0].next = 1, a[n + 1].pre = n;
24     for (int i = 1; i <= n; ++i) {
25         scanf("%d", &a[i].num);
26         a[i].pre = i - 1, a[i].next = i + 1;
27     }
28     for (int t = 1; t <= n - 1; ++t) {
29         int x, y, sum;
30         for (int i = a[0].next; ; i = a[i].next)
31             if (a[a[i].pre].num <= a[a[i].next].num) {
32                 x = i;
33                 break;
34             }
35         sum = a[a[x].pre].num + a[x].num;
36         for (int i = a[a[x].pre].pre; ; i = a[i].pre)
37             if (a[i].num > sum) {
38                 y = i;
39                 break;
40             }
41         del(x);
42         a[x].num = sum;
43         printf("%d ttt\n", sum);
44         insert(x, y);
45         ans += sum;
46     }
47     printf("%d", ans);
48     return 0;
49 }
Code Example

 

posted @ 2019-05-26 17:23  Mr^Kevin  阅读(1032)  评论(1编辑  收藏  举报