• 石子合并终极版 (GarsiaWachs算法) [o(n*n)] 板子


    [SDOI2008] 石子合并

    题目描述

    在一个操场上摆放着一排 N N N 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的 2 2 2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。

    试设计一个算法,计算出将 N N N 堆石子合并成一堆的最小得分。

    输入格式

    第一行一个整数 N N N

    接下来 N N N 行,第 i i i 行一个整数 a i a_i ai,代表第 i i i 堆石子的石子数。

    输出格式

    输出将所有石子合并为一堆的最小得分。

    样例 #1

    样例输入 #1

    4
    1
    1
    1
    1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    样例输出 #1

    8
    
    • 1

    提示

    $ N \leq 40000, a_i \leq 200$

    请注意 N N N 的范围

    GarsiaWachs算法


    设一个序列是A[0…n-1],
    每次寻找最小的一个满足A[k-1]<=A[k+1]的k,
    那么我们就把A[k]与A[k-1]合并,
    ans += (A[k]+A[k-1])
    之后从k向前寻找第一个满足A[j]>A[k]+A[k-1]的j,
    把合并后的值A[k]+A[k-1]插入A[j]的后面。


    板子

    #include <bits/stdc++.h>
    #define buff                     \
        ios::sync_with_stdio(false); \
        cin.tie(0);
    //#define int long long
    using namespace std;
    const int N = 1000;
    int n;
    vector<int> s;
    
    int func()
    {
        int idx = s.size() - 2;
    
        for (int i = 0; i < s.size() - 2; i++)
        {
            if (s[i] <= s[i + 2])
            {
                idx = i;
                break;
            }
        }
    
        int tt = s[idx] + s[idx + 1];
        s.erase(s.begin() + idx);
        s.erase(s.begin() + idx);
    
        int idx2 = -1;
    
        for (int i = idx - 1; i >= 0; i--)
        {
            if (s[i] > tt)
            {
                idx2 = i;
                break;
            }
        }
        s.insert(s.begin() + idx2 + 1, tt);
    
        return tt;
    }
    
    void solve()
    {
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            int t;
            cin >> t;
            s.push_back(t);
        }
    
        int ans = 0;
        for (int i = 1; i < n; i++)
            ans += func();
    
        cout << ans << '\n';
    }
    int main()
    {
        buff;
        solve();
    }
    /*
    设一个序列是A[0..n-1],
    每次寻找最小的一个满足A[k-1]<=A[k+1]的k,
    那么我们就把A[k]与A[k-1]合并,
    ans += (A[k]+A[k-1])
    之后从k向前寻找第一个满足A[j]>A[k]+A[k-1]的j,
    把合并后的值A[k]+A[k-1]插入A[j]的后面。
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
  • 相关阅读:
    正点原子FreeRTOS(中)
    PyQt5可视化编程-图形界面开发工具QtDesigner和PyUIC
    MyBatisPlus学习(2)—— 初始化环境配置 + 自定义Mapper
    STM32单片机入门学习(一)
    C++总结(9):Lambda表达式详解
    C51之智能感应垃圾桶
    【第006篇】通过impdp命令导入dmp文件到Oracle11g数据库中
    【Python爬虫项目实战四】Chatgpt国内接口分享第一期
    函数栈帧的创建和销毁
    微前端项目部署方案
  • 原文地址:https://blog.csdn.net/m0_60593173/article/details/125537295