1. 程式人生 > >石子合並問題 /// 區間DP oj2025

石子合並問題 /// 區間DP oj2025

opened CA ade ane pre script pac names 表示

Description

在一個圓形操場的四周擺放著n堆石子。現要將石子有次序地合並成一堆。

規定每次只能選相鄰的兩堆石子合並成新的一堆,並將新得的這堆石子數記為該次合並的得分。

試設計一個算法,計算出將n堆石子合並成一堆的最小得分和最大得分。

Input

輸入的第一行是正整數n,1 ≤ n ≤100,表示有n堆石子圍成環形。

第二行有n個數,分別表示每堆石子的個數。

Output

輸出的第一行中的數是最小得分;第二行中的數是最大得分。

Sample Input

4
4 4 5 9

Sample Output

43
54

技術分享圖片
#include <bits/stdc++.h>
#define
INF 0x3f3f3f3f using namespace std; int a[105],n; int dp0[105][105],dp1[105][105]; /// dp0[][],dp1[][]分別維護最小值和最大值 /// dp0[i][j]保存的是 以i為起點j為長度 時的總得分 int sum(int i,int l) { int s=0; for(int j=i;j<i+l;j++) s+=a[j%n]; return s; } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("
%d",&a[i]); for(int l=2;l<=n;l++) for(int i=0;i<n;i++) { dp0[i][l]=INF, dp1[i][l]=0; for(int j=1;j<l;j++) { int a=dp0[i][j],b=dp0[(i+j)%n][l-j], c=dp1[i][j],d=dp1[(i+j)%n][l-j]; dp0[i][l]
=min(dp0[i][l],a+b+sum(i,l)); dp1[i][l]=max(dp1[i][l],c+d+sum(i,l)); /// a+b + sum() /// 左右區間的總得分 + 合並左右區間的得分 /// 合並兩個區間的得分 = 兩區間內所有元素之和 } } int ans0=INF,ans1=0; for(int i=0;i<n;i++) ans0=min(ans0,dp0[i][n]), ans1=max(ans1,dp1[i][n]); printf("%d\n%d\n",ans0,ans1); return 0; }
View Code

石子合並問題 /// 區間DP oj2025