博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

洛谷P1880 石子合并(区间DP)(环形DP)

To 洛谷.1880 石子合并

题目描述

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

试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

输入输出格式

输入格式:

 

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

 

输出格式:

 

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

 

输入输出样例

输入样例#1:
4
4 5 9 4
输出样例#1:
43
54

代码:

先拆环为链,再做区间DP。

 1 #include<cstdio>
 2 #include<iostream>
 3 #define maxn 206
 4 using namespace std;
 5 int n,sum[maxn];
 6 int dpmin[maxn][maxn],dpmax[maxn][maxn];
 7 int main()
 8 {
 9     scanf("%d",&n);
10     for(int a,i=1;i<=n;i++)
11     {
12         scanf("%d",&a);
13         sum[i]=sum[i-1]+a;
14         sum[i+n]=sum[i];
15     }
16     for(int i=1;i<n;i++)
17       sum[i+n]+=sum[n];
18     for(int len=1;len<n;len++)
19       for(int i=1;i<=n*2-1-len;i++)
20       {
21             int j=i+len;
22             int res1=0x7fffffff;
23             int res2=-123456789;
24             for(int k=i;k<j;k++)
25             {
26               res1=min(res1,dpmin[i][k]+dpmin[k+1][j]+sum[j]-sum[i-1]);
27                 res2=max(res2,dpmax[i][k]+dpmax[k+1][j]+sum[j]-sum[i-1]);
28           }
29             dpmin[i][j]=res1;
30             dpmax[i][j]=res2;
31       }
32     int MIN=0x7fffffff,MAX=0;
33     for(int i=1;i<=n;i++)
34        MIN=min(dpmin[i][i+n-1],MIN),MAX=max(dpmax[i][i+n-1],MAX);//!dp[i][i+n-1]
35     printf("%d\n%d",MIN,MAX);
36     return 0;
37 }

 

posted @ 2017-05-07 13:15  SovietPower  阅读(247)  评论(0编辑  收藏  举报