P1880 [NOI1995]石子合并 区间dp+拆环成链

思路 :一道经典的区间dp  唯一不同的时候 终点和起点相连  所以要拆环成链  只需要把1-n的数组在n+1-2*n复制一遍就行了

#include<bits/stdc++.h>
using namespace std;
const int maxn=10005;
int dp[maxn][maxn],dp1[maxn][maxn];
const int INF=10000000;
int a[maxn];
int sum[maxn];
int dist(int x,int y){
//	cout<<sum[y]-sum[x-1]<<" ";
    return sum[y]-sum[x-1];

}

int main(){
      int n;
      cin>>n;
      sum[0]=0;
     for(int i=1;i<=n;i++){
         scanf("%d",&a[i]);//拆环
         a[i+n]=a[i];
         
     }
     for(int i=1;i<=2*n;i++){
         sum[i]=sum[i-1]+a[i];
     }

     for(int len=2;len<=n;len++){
       for(int i=1;i<=n*2;i++){
           int j=i+len-1;
           if(j>2*n)break;
           dp1[i][j]=INF;
           for(int k=i;k<j;k++){
               dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+dist(i,j)); //区间dp
               dp1[i][j]=min(dp1[i][j],dp1[i][k]+dp1[k+1][j]+dist(i,j));
           }
       }
     }
      int ans1=0,ans2=1000000;
      for(int i=1;i<=n;i++){
          ans1=max(dp[i][i+n-1],ans1);
          ans2=min(ans2,dp1[i][i+n-1]);
         // cout<<dp1[i][i+n-1]<<" ";	
         }
      cout<<ans2<<endl<<ans1<<endl;
     

       
    
    return 0;
}

  

原文地址:https://www.cnblogs.com/ttttttttrx/p/9885900.html