演算法提高 合併石子(區間dp,四邊形不等式優化)

2021-08-14 13:36:30 字數 2016 閱讀 9454

時間限制:2.0s 記憶體限制:256.0mb

提交此題

問題描述

在一條直線上有n堆石子,每堆有一定的數量,每次可以將兩堆相鄰的石子合併,合併後放在兩堆的中間位置,合併的費用為兩堆石子的總數。求把所有石子合併成一堆的最小花費。

輸入格式

輸入第一行包含乙個整數n,表示石子的堆數。

接下來一行,包含n個整數,按順序給出每堆石子的大小 。

輸出格式

輸出乙個整數,表示合併的最小花費。

樣例輸入

5 1 2 3 4 5

樣例輸出

33 資料規模和約定

1<=n<=1000, 每堆石子至少1顆,最多10000顆。

#include 

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define mem(a,n) memset(a,n,sizeof(a))

#define rep(i,a,n) for(int i=a;i#define pb push_back

typedef

long

long ll;

const

int inf=0x3f3f3f3f;

const

double pi=3.1415926;

const

int n=1e3+5;

int sum[n],dp[n][n];

/**思路:貪心法只是區域性最優, (區間dp)全域性最優 通過區域性最優求解

dp[i][j]= 0 ; i = j時

min(dp[j][j],dp[i][k]+dp[k+1][j) + (sum[j] - sum[i-1]); i != j時

**/int main()

for(int r=2; r<=n; r++)///求區間長度r的最小值

dp[i][j]+=(sum[j]-sum[i-1]);///放在迴圈內部會tle}}

printf("%d\n",dp[1][n]);

}return

0;}

#include 

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define mem(a,n) memset(a,n,sizeof(a))

#define rep(i,a,n) for(int i=a;i#define pb push_back

typedef long long ll;

const int inf=0x3f3f3f3f;

const double pi=3.1415926;

const int n=1e3+5;

int sum[n],dp[n][n],p[n][n];

/**思路:貪心法只是區域性最優, (區間dp)全域性最優 通過區域性最優求解

dp[i][j]= 0 ; i = j時

min(dp[j][j],dp[i][k]+dp[k+1][j) + (sum[j] - sum[i-1]); i != j時

**/int main()

for(int r=2; r<=n; r++)///求區間長度r的最小值

}dp[i][j]+=(sum[j]-sum[i-1]);}}

printf("%d\n",dp[1][n]);

}return 0;

}

石子合併 四邊形優化

動態規劃的經典題目,在遇到狀態轉移方程像min w i k w k 1 j m i j 的時候就可以使用考慮使用四邊形優化。在i i j j 的條件滿足的情況下,有w i j w i j w i j w i j 那麼就可以使用s i j 同時s i j 又有單調遞增性 並沒有仔細看 以後有時間一定補...

石子合併 四邊形優化

description 在乙個操場上擺放著一排n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。試設計乙個演算法,計算出將n堆石子合併成一堆的最小得分。input 第一行是乙個數n。以下n行每行乙個數a,表示石子數目。outpu...

區間DP入門 四邊形優化

區間dp,顧名思義,求區間最值問題。通過合併小區間最優解來更新大區間,然後逐漸更新出答案。要求解在乙個區間上的最優解,那麼就要把這個區間分割成乙個個小區間,求解每個小區間的最優解,再合併小區間得到大區間。所以在 實現上,先列舉區間長度len為每次分割成的小區間長度 由短到長不斷合併 內層列舉該長度下...