agc035D
题意
给定n个数字。每次选择三个连续的位置,删去中间的数,将中间的数的值加在左右的两个数上。最小化剩下的两个数的和。
题解
我们把删数的过程反过来看做吐数的过程:最开始只有两个数,其他的数字将会被填在他们两个之间。最开始的两个数对目标函数的贡献都是1。
考虑我们现在剩下k张牌,他们对目标函数的贡献分别是那么如果我们在第个数和第 个数之间插入一个数,这个数对目标函数的贡献要乘以。
那么构思一个, 表示区间张卡片对目标函数的贡献,那么每次我们选择区间中的一个数来作为这个区间中第一被吐出来的数。
#include <bits/stdc++.h>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define dow(i,j,k) for (int i = j; i >= k; i--)
#define fi first
#define se second
#define mp make_pair
#define pb push_back
using namespace std;
typedef pair<int, int> pi;
typedef long long ll;
int n;
ll a[20];
long long ans;
ll find(int l, int xl, int r, int xr) {
if (l + 1 == r) return 0;
long long res = 1e18;
for (int i = l + 1; i < r; i++)
res = min(res, find(l, xl, i, xl + xr) + find(i, xl + xr, r, xr) + a[i] * (xl + xr));
return res;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
cout << find(1, 1, n, 1) + a[1] + a[n] << endl;
}