第十一届蓝桥杯 ——超级胶水
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
1≤n≤105
1
≤
w
i
≤
1000
1≤w_i≤1000
1≤wi≤1000
题解一:区间DP(超时,超内存)
f [ l ] [ r ] : 将 第 l 堆 石 子 到 第 r 堆 石 子 合 并 成 一 堆 石 子 的 最 小 代 价 。 f[l][r]:将第l堆石子到第r堆石子合并成一堆石子的最小代价。 f[l][r]:将第l堆石子到第r堆石子合并成一堆石子的最小代价。
#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 a∗b
若有三堆石子 [a, b, c]
:
- 假设先合并 [ a , b ] [a, b] [a,b],再合并 [ c ] [c] [c],代价为 a ∗ b + ( a + b ) ∗ c a*b + (a + b)*c a∗b+(a+b)∗c,化简得 a ∗ b + a ∗ c + b ∗ c a*b+a*c+b*c a∗b+a∗c+b∗c;
- 假设先合并 [ b , c ] [b, c] [b,c],再合并 [ a ] [a] [a],代价为 b ∗ c + ( b + c ) ∗ a b * c + (b + c)*a b∗c+(b+c)∗a,化简得 a ∗ b + a ∗ c + b ∗ c a*b+a*c+b*c a∗b+a∗c+b∗c;
若有四堆石子 [a, b, c, d]
:
- 假设先合并 [ 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 a∗b+(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 a∗b+a∗c+a∗d+b∗c+b∗d+c∗d;
- 假设先合并 [ 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 b∗c+(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 a∗b+a∗c+a∗d+b∗c+b∗d+c∗d;
- 以此类推
结论
:由上可知,通过不同的合并顺序最终都能得到相同的答案;
公式
:
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(Wi∗S[i−1]),
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;
以上是关于第十一届蓝桥杯 ——超级胶水的主要内容,如果未能解决你的问题,请参考以下文章