1. 程式人生 > >1148環形石子合併

1148環形石子合併

1148.石子合併

時限:1000ms 記憶體限制:10000K  總時限:3000ms

描述

在一個圓形操場的四周擺放著n堆石子(n<= 100),現要將石子有次序地合併成一堆。規定每次只能選取相鄰的兩堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。編一程式,讀入石子堆數n及每堆的石子數(<=20)。選擇一種合併石子的方案,使得做n-1次合併,得分的總和最小;比如有4堆石子:4 4 5 9 則最佳合併方案如下: 4 4 5 9 score: 0 8 5 9 score: 8 13 9 score: 8 + 13 = 21 22 score: 8 + 13 + 22 = 43

輸入

可能有多組測試資料。 當輸入n=0時結束! 第一行為石子堆數n(1<=n<=100);第二行為n堆的石子每堆的石子數,每兩個數之間用一個空格分隔。

輸出

合併的最小得分,每個結果一行。

輸入樣例

4 4 4 5 9 0

輸出樣例

43

#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,minh,minm; int a[210]; int m[210][210];//m[i][j]記錄從第i個到第j個石子堆合併的最小得分 int sum(int i,int j) {     int s=0;     for(int k=i;k<=j;k++)     {         s+=a[k];     }     return s; } int minscore() {     int t;     for(int i=1;i<=2*n-1;i++)     {         m[i][i]=0;     }     for(int i=1;i<2*n-1;i++)     {         m[i][i+1]=a[i]+a[i+1];//相鄰兩個合併的和     }     for(int i=2;i<=2*n-1;i++)//表示間隔大小     {         for(int j=1;j<=2*n-1-i;j++)//1 3  2 4  3 5   4 6             {                 //計算m[j][i+j]的最小值                 minh=m[j+1][i+j]+a[j]+sum(j+1,i+j);                 for(int k=1;k<i;k++)                 {                     if(j+k+1==i+j)                     {                         t=m[j][j+k]+sum(j,j+k)+a[i+j];                     }                     else                     {                         t=(m[j][j+k]+m[j+k+1][i+j])+sum(j,j+k)+sum(j+k+1,i+j);                     }                     if(minh>t)                     {                         minh=t;

                    }                 }                 m[j][i+j]=minh;             }     }     minm=99999999;     for(int i=1;i<=2*n-n;i++)     {         if(m[i][i+n-1]<minm)         {             minm=m[i][i+n-1];         }

    }     return minm; } int main() {     while(cin>>n)     {         if(n==0)break;         memset(a,0,sizeof(a));         memset(m,0,sizeof(m));         for(int i=1;i<=n;i++)         {             cin>>a[i];         }         for(int i=1;i<=n-1;i++)         {             a[i+n]=a[i];         }         cout<<minscore()<<endl;     }     return 0; }