分析:记dp[i][j]为从i到j合并的最小代价(顺时针,i可以大于j),sum[i][j]为从i到j的和,则dp[i][j]=min{dp[i][k-1]+dp[k][j]}+sum[i][j],(i<k<=j),直接求的话复杂度为O(n^3),会T。
四边形不等式优化:记s[i][j]为dp[i][j]取得最小值时对应的k值,则有dp[i][j]=min{dp[i][k-1]+dp[k][j]}+sum[i][j],(s[i][j-1]<=k<=s[i+1][j]),可以证明,复杂度为O(n^2)。
最近在学java,就用java 写了。。
1 import java.io.*; 2 import java.math.*; 3 import java.util.*; 4 public class Main { 5 static int dp[][],sum[][],n,s[][];15 public static void main(String arg[]){ 16 Scanner sc=new Scanner(System.in); 17 n=sc.nextInt(); 18 dp=new int[n][n]; 19 sum=new int[n][n]; 20 s=new int[n][n]; 21 for(int i=0;i<n;i++){ 22 for(int j=0;j<n;j++){ 23 dp[i][j]=-1; 24 } 25 } 26 for(int i=0;i<n;i++){ 27 sum[i][i]=sc.nextInt(); 28 dp[i][i]=0; 29 s[i][i]=i; 30 } 31 for(int i=0;i<n;i++){ 32 for(int j=i+1;j<n;j++){ 33 sum[i][j]=sum[i][j-1]+sum[j][j]; 34 } 35 } 36 for(int i=0;i<n;i++){ 37 for(int j=0;j<i;j++){ 38 sum[i][j]=sum[0][j]+sum[i][n-1]; 39 } 40 } 41 for(int step=1;step<n;step++){ 42 for(int i=0;i<n;i++){ 43 int j=(i+step)%n; 44 dp[i][j]=1000000000; 45 for(int k=s[i][(j-1+n)%n];k!=s[(i+1)%n][j]+1;k++){ 46 if(k>=n)k=0; 47 if(k==i)continue; 48 if(dp[i][j]>dp[i][(k-1+n)%n]+dp[k][j]){ 49 dp[i][j]=dp[i][(k-1+n)%n]+dp[k][j]; 50 s[i][j]=k; 51 } 52 } 53 dp[i][j]+=sum[i][j]; 54 } 55 } 56 int ans=dp[0][n-1]; 57 for(int i=1;i<n;i++){ 58 ans=Math.min(ans,dp[i][-1+i]); 59 } 60 System.out.println(ans); 61 } 62 }