将经典的合并石子改成首位相连,即第一堆可以和最后一堆合并。
只需要预处理一下,将1到n-1堆石子放到n后面,重新构造出线性序列即可。
因为在环状序列中,最后的结果肯定是由最开始的某个[k,k+n-1]区间得到的。
代码:(找不到题目,不知正确性如何)
/*
* @Author: hesorchen
* @Date: 2020-12-30 16:53:18
* @LastEditTime: 2021-01-26 16:27:50
* @Description: 栽种绝处的花
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
int a[210];
int sum[210];
int dp[210][210];
int main()
{
memset(dp, 0x3f3f3f3f, sizeof dp);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = n + 1; i < 2 * n; i++) //拆解成线性序列
a[i] = a[i - n];
for (int i = 1; i < 2 * n; i++)
{
dp[i][i] = 0;
sum[i] = sum[i - 1] + a[i];
}
for (int i = 2; i <= n; i++)
{
for (int l = 1; l + i - 1 < 2 * n; l++)
{
int r = l + i - 1;
for (int mid = l; mid < r; mid++)
{
dp[l][r] = min(dp[l][r], dp[l][mid] + dp[mid + 1][r] + sum[r] - sum[l - 1]);
}
}
}
int ans = 0x3f3f3f3f;
for (int i = 1; i <= n; i++) //枚举每个长度为n的区间 取最优解
ans = min(dp[i][i + n - 1], ans);
cout << ans << endl;
return 0;
}