題目
設(shè)有 N 堆石子排成一排,其編號為 1,2,3,…,N。
每堆石子有一定的質(zhì)量,可以用一個整數(shù)來描述,現(xiàn)在要將這 N 堆石子合并成為一堆。
每次只能合并相鄰的兩堆,合并的代價為這兩堆石子的質(zhì)量之和,合并后與這兩堆石子相鄰的石子將和新堆相鄰,合并時由于選擇的順序不同,合并的總代價也不相同。
例如有 4 堆石子分別為 1 3 5 2 , 我們可以先合并 1、2堆,代價為 4,得到 4 5 2 , 又合并 1、2堆,代價為 9,得到 9 2 ,再合并得到 11,總代價為 4+9+11=24;
如果第二步是先合并 2、3 堆,則代價為 7,得到 4 7 ,最后一次合并代價為 11,總代價為 4+7+11=22。
問題是:找出一種合理的方法,使總的代價最小,輸出最小代價。
輸入格式
第一行一個數(shù) N 表示石子的堆數(shù) N。
第二行 N 個數(shù),表示每堆石子的質(zhì)量(均不超過 1000)。
輸出格式
輸出一個整數(shù),表示最小代價。
數(shù)據(jù)范圍
1≤N≤300
輸入樣例:
輸出樣例:
解題思路:
按區(qū)間從短到長依次枚舉,求區(qū)間中石子合并的最小代價并記錄在f數(shù)組中
例如
區(qū)間長度len=2時得到
f[1][2] = 4,f[2][3] = 8,f[3][4] = 7
在區(qū)間長度len=3時根據(jù)f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);就可以得到
f[1][3]=f[1][2]+f[3][3]+(s[3]-s[0])=13
ps:區(qū)間長度遞增的原因是區(qū)間長度長的利用到了區(qū)間長度小的數(shù)值
程序代碼
#include<bits/stdc++.h> const int N=1010; int f[N][N];//表示區(qū)間 int s[N]; //求前綴和 int a; using namespace std; int main() { cin>>a; for(int i=1;i<=a;i++)cin>>s[i]; for(int i=1;i<=a;i++)s[i]+=s[i-1];//求前綴和,使得下標(biāo)之差就是區(qū)間的元素之和 for(int len=2;len<=a;len++)//len代表區(qū)間的長度,區(qū)間的長度遞增 { for(int i=1;i+len-1<=a;i++)//例如,i=1,len=2時 i+len-1=2,1到2即表示區(qū)間長度為2 { int l=i,r=i+len-1; f[l][r]=0x3f3f3f3f; for(int k=l;k<r;k++)//k用來切割區(qū)間 { f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]); //區(qū)間從左到右依次分割求理想的最小值 } //s[r]-s[l-1]為最后一下合并區(qū)間內(nèi)的石子需要的體力為區(qū)間內(nèi)所有石子的和 } } cout<<f[1][a];//輸出1到a區(qū)間的最小和,就是答案 }
|