一條直線上擺放着一行共n堆的石子。現要將石子有序地合並成一堆。規定每次只能選相鄰的兩堆合並成新的一堆,並將新的一堆石子數記為該次合並的得分。
請編輯計算出將n堆石子合並成一堆的最小得分和將n堆石子合並成一堆的最大得分。
Input
輸入有多組測試數據。
每組第一行為n(n<=100),表示有n堆石子,。
二行為n個用空格隔開的整數,依次表示這n堆石子的石子數量ai(0<ai<=100)
Output
每組測試數據輸出有一行。輸出將n堆石子合並成一堆的最小得分和將n堆石子合並成一堆的最大得分。 中間用空格分開。
間用空格分開。
Sample Input
3
1 2 3
Sample Output
9 11
1 #include<iostream> 2 #include <cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 8 int dp[105][105]; 9 int sum[110]; 10 int ans=0,cnt=0; 11 12 int dfs(int l,int r){/*求最大*/ 13 if(dp[l][r]!=-1){ 14 return dp[l][r]; 15 } 16 if(r-l==1)return sum[r]-sum[l-1]; 17 if(r==l) return 0; 18 int &res=dp[l][r]; 19 res=-INF; 20 for(int k=l;k<r;k++){ 21 res=max(res,dfs(l,k)+dfs(k+1,r)); 22 } 23 res+=sum[r]-sum[l-1]; 24 return res; 25 } 26 27 int dfs2(int l,int r){/*求最小*/ 28 if(dp[l][r]!=-1) return dp[l][r]; 29 if(r-l==1) return sum[r]-sum[l-1]; 30 if(r==l) return 0; 31 dp[l][r]=INF; 32 for( int k=l; k<r; k++ ){ 33 dp[l][r]=min(dp[l][r],dfs2(l,k)+dfs2(k+1,r)); 34 } 35 dp[l][r]+=sum[r]-sum[l-1]; 36 return dp[l][r]; 37 } 38 39 int main(){ 40 int n; 41 memset(sum,0,sizeof(sum)); 42 while(~scanf("%d",&n)&&n){ 43 for( int i=1; i<=n; i++ ){ 44 int t; 45 cin>>t; 46 sum[i]=sum[i-1]+t; 47 } 48 memset(dp,-1,sizeof(dp)); 49 ans=dfs2(1,n); 50 memset(dp,-1,sizeof(dp)); 51 cnt=dfs(1,n); 52 cout<<ans<<" "<<cnt<<endl; 53 } 54 55 return 0; 56 }