動態規劃 區間合併,合併相鄰的石子

設有N堆石子排成一排,其編號爲1,2,3,…,N。

每堆石子有一定的質量,可以用一個整數來描述,現在要將這N堆石子合併成爲一堆。

每次只能合併相鄰的兩堆,合併的代價爲這兩堆石子的質量之和,合併後與這兩堆石子相鄰的石子將和新堆相鄰,合併時由於選擇的順序不同,合併的總代價也不相同。

例如有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。

問題是:找出一種合理的方法,使總的代價最小,輸出最小代價。

輸入格式

第一行一個數N表示石子的堆數N。

第二行N個數,表示每堆石子的質量(均不超過1000)。

輸出格式

輸出一個整數,表示最小代價。

數據範圍

1≤N≤300

輸入樣例:

4
1 3 5 2

輸出樣例:

22

 

#include<iostream>
using namespace std;
const int N=310;

int s[N];//前綴和
int f[N][N];//全局變量默認初始化爲0
int n;

int main(){
    cin>>n;
    for (int i=1;i<=n;i++){
         cin>>s[i];
         s[i] += s[i-1];
    }
    
    for (int len =2;len<=n;len++){//區間長度,從2開始,如果從1開始的話就只有一堆了不需要合併,先枚舉區間長度
        for (int i=1;i+len-1<=n;i++){//再枚舉區間左端點,右端點爲i+len-1,要<-n;
            int j = i+len-1;//右端點
            f[i][j] = 1e8;
            for(int k=i;k<j;k++){// i,j區間段
                f[i][j] = min(f[i][j],f[i][k]+f[k+1][j] +s[j]-s[i-1]);
            }
        }
    }
    cout<<f[1][n]<<endl;
    return 0;
}

 題目來源:

https://www.acwing.com/problem/content/description/284/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章