Topic link: HDU3506 Monkey Party
Question: Similar to merging stones in a circle, the cost of merging two piles of stones is the sum of the number of the two piles of stones. Ask the minimum cost of merging all stones;
Analysis: dp[i][j] represents the minimum cost of the interval [i,j], p[i][j] represents the number of stones in the interval [i,j], adding quadrilateral inequality optimization, s[i][ j] represents the best breakpoint in the interval [i,j];
[Optimization of Quadrilateral Inequality]
When a<b<=c<d, if f[a][c]+f[b][d]<=f[b][c]+f[a][d], f satisfies the quadrilateral Inequality, at this time the best breakpoint s[i][j] satisfies the property:
s[i][j-1]<=s[i][j]<=s[i+1][j]
In this way, the original enumeration interval start point and breakpoint n*n are optimized to n
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=2007;
int dp[maxn][maxn],s[maxn][maxn],p[maxn][maxn],a[maxn];
int n,ans;
void rua()
{
for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i+n]=a[i];
memset(dp,INF,sizeof(dp));
memset(s,0,sizeof(s));
for(int i=1;i<=n+n;i++)
{
dp[i][i]=0;
s[i][i]=i;
p[i][i]=a[i];
}
for(int i=1;i<n;i++)//区间长度
for(int j=1;i+j<2*n;j++)//区间起点
for(int k=s[j][i+j-1];k<=s[j+1][i+j];k++)
{
int tmp=p[j][k]+p[k+1][i+j];
if(dp[j][i+j]>dp[j][k]+dp[k+1][i+j]+tmp)
{
p[j][i+j]=tmp;
dp[j][i+j]=dp[j][k]+dp[k+1][i+j]+tmp;
s[j][i+j]=k;
}
}
ans=INF;
for(int i=1;i<=n+1;i++) ans=min(ans,dp[i][i+n-1]);
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d",&n)) rua();
return 0;
}