1. 程式人生 > >石子合並 區間dp模板

石子合並 區間dp模板

輸入數據 max rip using memset 排列 for gin spa

題意:中文題

Description

在操場上沿一直線排列著 n堆石子。現要將石子有次序地合並成一堆。規定每次只能選相鄰的兩堆石子合並成新的一堆, 並將新的一堆石子數記為該次合並的得分。允許在第一次合並前對調一次相鄰兩堆石子的次序。

計算在上述條件下將n堆石子合並成一堆的最小得分。

Input

輸入數據共有二行,其中,第1行是石子堆數n≤100;
第2行是順序排列的各堆石子數(≤20),每兩個數之間用空格分隔。

Output

輸出合並的最小得分。

Sample Input

3 2 5 1

Sample Output

11

Source

NOI1995

題解:區間dp,交換的處理 代碼
#include<iostream>
#include
<cstdlib> #include<algorithm> using namespace std; #define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++) #define per(i,j,k) for(int i = (int)j;i >= (int)k;i --) #define mmm(a,b) memset(a,b,sizeof(a)) #define pb push_back #define mp make_pair; const int maxn=1e2+5; int n; int a[maxn];
int dp[maxn][maxn]; int main() { cin >> n; //fill(dp, dp + maxn*maxn, 1e9); int ans = 1e9; rep(i, 1, n)cin >> a[i], dp[i][i] = 0; rep(i, 1, n-1) { swap(a[i], a[i + 1]); rep(len, 2, n)//len rep(i, 1, n - len + 1)//begin { dp[i][i
+ len - 1] = 1e9; int sum = 0; rep(j, i, i + len - 1)sum += a[j]; rep(k, i, len + i - 2)//k { dp[i][i + len - 1] = min(dp[i][i + len - 1], dp[i][k] + dp[k + 1][i + len - 1] + sum); } } ans=min(ans,dp[1][n]); swap(a[i], a[i + 1]); } cout << ans; cin >> n; }

石子合並 區間dp模板