您的位置:首页 > 其它

133.石子归并 2

2016-04-07 13:51 134 查看


2102 石子归并 2[/b]

时间限制: 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

经典的区间动态规划。


分类标签 Tags 点此展开

动态规划 区间型DP 环型DP

DP:因为石子绕成一个环,不是一条直线,所以dp[i][j]的含义应为从第i堆开始,合并j堆石子能得到的最优值

则易得状态转移方程为

dp1[i][j]=better(dp1[i][j],dp1[i][k]+dp1[(i+k-1)%n+1][j-k]+sum[i][j]);

代码:

#include

#include

using namespace std;

#include

#define INFn 101

int
dpmin[INFn][INFn],dpmax[INFn][INFn],n,num[INFn],sum[INFn][INFn];

void input()

{

scanf("%d",&n);

for(int i=1;i<=n;++i)

{

scanf("%d",&num[i]);

sum[i][1]=num[i];//sum储存的是从i开始合并几堆的花费

}

for(int
j=2;j<=n;++j)

for(int
i=1;i<=n;++i)

sum[i][j]=sum[i%n+1][j-1]+num[i];

for(int i=1;i<=n;++i)

dpmin[i][1]=dpmax[i][1]=0;

}

void dp()

{

for(int
j=2;j<=n;++j)//仍然要把j循环放在外面

for(int
i=1;i<=n;++i)

{

dpmin[i][j]=9999999;//对当前更新的dp的预处理

dpmax[i][j]=0;

for(int
k=1;k<=j-1;++k)

{

dpmin[i][j]=min(dpmin[i][j],dpmin[i][k]+dpmin[(i+k-1)%n+1][j-k]+sum[i][j]);

dpmax[i][j]=max(dpmax[i][j],dpmax[i][k]+dpmax[(i+k-1)%n+1][j-k]+sum[i][j]);

}

}

}

int main()

{

input();

dp();

int
ansmax=0,ansmin=INFn*INFn*INFn;

for(int i=1;i<=n;++i)

{

if(dpmin[i]

ansmin=dpmin[i]
;

if(dpmax[i]
>ansmax)

ansmax=dpmax[i]
;

}

printf("%d\n%d",ansmin,ansmax);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: