Codevs_2102_石子归并2_(环状动态规划)

描述


http://codevs.cn/problem/2102/

2102 石子归并 2

 

时间限制: 10 s
空间限制: 256000 KB
题目等级 : 黄金 Gold
 
 
 
 
 
题目描述 Description

在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

输入描述 Input Description

数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

输出描述 Output Description

输出共2行,第1行为最小得分,第2行为最大得分.

样例输入 Sample Input

4
4 4 5 9

样例输出 Sample Output

43
54

数据范围及提示 Data Size & Hint

经典的区间动态规划。

分析


枚举起点即可.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=100+5,INF=0x7fffffff;
 5 
 6 int n,ans1,ans2;
 7 int s[maxn<<1],dp1[maxn][maxn],dp2[maxn][maxn];
 8 
 9 void solve(){
10     ans1=INF, ans2=-INF;
11     for(int q=1;q<=n;q++){
12         for(int r=2;r<=n;r++)
13             for(int i=q;i<=q+n-r;i++){
14                 int j=i+r-1;
15                 dp1[i-q+1][j-q+1]=INF; dp2[i-q+1][j-q+1]=-INF;
16                 for(int k=i;k<j;k++){
17                     dp1[i-q+1][j-q+1]=min(dp1[i-q+1][j-q+1],dp1[i-q+1][k-q+1]+dp1[k+1-q+1][j-q+1]+s[j]-s[i-1]);
18                     dp2[i-q+1][j-q+1]=max(dp2[i-q+1][j-q+1],dp2[i-q+1][k-q+1]+dp2[k+1-q+1][j-q+1]+s[j]-s[i-1]);
19                 }
20             }
21         ans1=min(dp1[1][n],ans1);
22         ans2=max(dp2[1][n],ans2);
23     }
24     printf("%d\n%d\n",ans1,ans2);
25 }
26 void init(){
27     scanf("%d",&n);
28     for(int i=1;i<=n;i++){
29         int t; scanf("%d",&t);
30         s[i]=s[i-1]+t;
31     }
32     for(int i=n+1;i<=n*2;i++) s[i]=s[i-n]+s[n];
33 }
34 int main(){
35     init();
36     solve();
37     return 0;
38 }
View Code

 

posted @ 2016-05-24 19:40  晴歌。  阅读(249)  评论(0编辑  收藏  举报