第十一届蓝桥杯 ——超级胶水

Posted 业余算法学徒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十一届蓝桥杯 ——超级胶水相关的知识,希望对你有一定的参考价值。

题目描述
小明有 n n n 颗石子,按顺序摆成一排,他准备用胶水将这些石子粘在一起。

每颗石子有自己的重量,如果将两颗石子粘在一起,将合并成一颗新的石子,重量是这两颗石子的重量之和。

为了保证石子粘贴牢固,粘贴两颗石子所需要的胶水与两颗石子的重量乘积成正比,本题不考虑物理单位,认为所需要的胶水在数值上等于两颗石子重量的乘积。

每次合并,小明只能合并位置相邻的两颗石子,并将合并出的新石子放在原来的位置。

现在,小明想用最少的胶水将所有石子粘在一起,请帮助小明计算最少需要多少胶水。

输入格式
输入的第一行包含一个整数 n n n,表示初始时的石子数量。

第二行包含 n n n 个整数 w 1 , w 2 , … , w n w_1,w_2,…,w_n w1,w2,,wn,依次表示每颗石子的重量。

输出格式
一个整数表示答案。

输入样例1
3
3 4 5

输出样例1
47

输入样例2
8
1 5 2 6 3 7 4 8

输出样例2
546

数据范围
1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105
1 ≤ w i ≤ 1000 1≤w_i≤1000 1wi1000


题解一:区间DP(超时,超内存)

f [ l ] [ r ] : 将 第 l 堆 石 子 到 第 r 堆 石 子 合 并 成 一 堆 石 子 的 最 小 代 价 。 f[l][r]:将第l堆石子到第r堆石子合并成一堆石子的最小代价。 f[l][r]lr

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 100010;

int n;
int s[N];
int f[1010][1010];

int main()

    cin >> n;
    for (int i = 1; i <= n; i ++) 
    
        cin >> s[i];
        s[i] += s[i - 1];
    
    
    memset(f, 0x3f, sizeof f);
    for (int len = 1; len <= n; len ++)
        for (int l = 1; l + len - 1 <= n; l ++)
        
            int r = l + len - 1;
            if(len == 1) f[l][r] = 0;
            for (int k = l; k <= r; k ++)
                f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r] + (s[k] - s[l - 1]) * (s[r] - s[k]));
        
    
    cout << f[1][n] << endl;    
    return 0;

题解二:推公式

若有两堆石子 [a, b]

  • 代价: a ∗ b a*b ab

若有三堆石子 [a, b, c]

  1. 假设先合并 [ a , b ] [a, b] [a,b],再合并 [ c ] [c] [c],代价为 a ∗ b + ( a + b ) ∗ c a*b + (a + b)*c ab+(a+b)c,化简得 a ∗ b + a ∗ c + b ∗ c a*b+a*c+b*c ab+ac+bc
  2. 假设先合并 [ b , c ] [b, c] [b,c],再合并 [ a ] [a] [a],代价为 b ∗ c + ( b + c ) ∗ a b * c + (b + c)*a bc+(b+c)a,化简得 a ∗ b + a ∗ c + b ∗ c a*b+a*c+b*c ab+ac+bc

若有四堆石子 [a, b, c, d]

  1. 假设先合并 [ a , b ] [a, b] [a,b],再合并 [ c ] [c] [c],最后合并 [ d ] [d] [d],代价为 a ∗ b + ( a + b ) ∗ c + ( a + b + c ) ∗ d a*b + (a + b)*c + (a + b + c) * d ab+(a+b)c+(a+b+c)d,化简得 a ∗ b + a ∗ c + a ∗ d + b ∗ c + b ∗ d + c ∗ d a*b+a*c+a*d+b*c+b*d+c*d ab+ac+ad+bc+bd+cd
  2. 假设先合并 [ b , c ] [b, c] [b,c],再合并 [ a ] [a] [a],最后合并 [ d ] [d] [d],代价为 b ∗ c + ( b + c ) ∗ a + ( a + b + c ) ∗ d b * c + (b + c)*a+(a+b+c)*d bc+(b+c)a+(a+b+c)d,化简得 a ∗ b + a ∗ c + a ∗ d + b ∗ c + b ∗ d + c ∗ d a*b+a*c+a*d+b*c+b*d+c*d ab+ac+ad+bc+bd+cd
  3. 以此类推

结论:由上可知,通过不同的合并顺序最终都能得到相同的答案;

公式 a n s = a n s +   ∑ i = 1 n ( W i ∗ S [ i − 1 ] ) ans = ans +\\ \\sum_i=1^n(W_i * S[i-1]) ans=ans+ i=1n(WiS[i1]) W i W_i Wi 是每个石子的重量, S S S 是前缀和数组;

#include <iostream>
using namespace std;

typedef long long LL;

int main()

    int n;
    cin >> n;
    
    LL prev = 0, ans = 0;
    for (int i = 1; i <= n; i ++)
    
        int w;
        cin >> w;
        ans += w * prev;
        prev += w;
    
    
    cout << ans << endl;


蓝桥杯C/C++省赛历年题

以上是关于第十一届蓝桥杯 ——超级胶水的主要内容,如果未能解决你的问题,请参考以下文章

第十一届蓝桥杯 ——超级胶水

第十一届蓝桥杯省赛第一场C++ A/B组 真题题解(详细讲解+代码分析)看这篇就够了~~~

第十四届蓝桥杯大赛软件赛省赛JavaB组解析

蓝桥杯:合并石子(区间DP+平行四边形优化)

第十四届蓝桥杯三月真题刷题训练——第 12 天

第十一届蓝桥杯模拟赛(二)