石子合並問題 /// 區間DP oj2025
阿新 • • 發佈:2018-05-27
opened CA ade ane pre script pac names 表示
Description
在一個圓形操場的四周擺放著n堆石子。現要將石子有次序地合並成一堆。
規定每次只能選相鄰的兩堆石子合並成新的一堆,並將新得的這堆石子數記為該次合並的得分。
試設計一個算法,計算出將n堆石子合並成一堆的最小得分和最大得分。
Input輸入的第一行是正整數n,1 ≤ n ≤100,表示有n堆石子圍成環形。
第二行有n個數,分別表示每堆石子的個數。
Output輸出的第一行中的數是最小得分;第二行中的數是最大得分。
Sample Input4
4 4 5 9
43
54
#include <bits/stdc++.h> #defineView CodeINF 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; }
石子合並問題 /// 區間DP oj2025