2298 石子合并 2008年省队选拔赛山东

题目描述 Description

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

  试设计一个算法,计算出将N堆石子合并成一堆的最小得分。

输入描述 Input Description

  第一行是一个数N。

  以下N行每行一个数A,表示石子数目。

输出描述 Output Description

  共一个数,即N堆石子合并成一堆的最小得分。

样例输入 Sample Input

4

1

1

1

1

样例输出 Sample Output

8

数据范围及提示 Data Size & Hint

对于 30% 的数据,1≤N≤100

对于 60% 的数据,1≤N≤1000

对于 100% 的数据,1≤N≤40000

对于 100% 的数据,1≤A≤200

思路:

1. 这类题目一开始想到是DP, 设dp[i][j]表示第i堆石子到第j堆石子合并最小得分.

状态方程: dp[i][j] = min(dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);

sum[i]表示第1到第i堆石子总和. 递归记忆化搜索即可.

2. 不过此题有些不一样, 1<=n<=50000范围特大, dp[50000][50000]开不到这么大数组.

问题分析:

(1). 假设我们只对3堆石子a,b,c进行比较, 先合并哪2堆, 使得得分最小.

score1 = (a+b) + ( (a+b)+c )

score2 = (b+c) + ( (b+c)+a )

再次加上score1 <= score2, 化简得: a <= c, 可以得出只要a和c的关系确定,

合并的顺序也确定.

(2). GarsiaWachs算法, 就是基于(1)的结论实现.找出序列中满足stone[i-1] <=

stone[i+1]最小的i, 合并temp = stone[i]+stone[i-1], 接着往前面找是否

有满足stone[j] > temp, 把temp值插入stone[j]的后面(数组的右边). 循环

这个过程一直到只剩下一堆石子结束.

(3). 为什么要将temp插入stone[j]的后面, 可以理解为(1)的情况

从stone[j+1]到stone[i-2]看成一个整体 stone[mid],现在stone[j],

stone[mid], temp(stone[i-1]+stone[i-1]), 情况因为temp < stone[j],

因此不管怎样都是stone[mid]和temp先合并, 所以讲temp值插入stone[j]

的后面是不影响结果.

 1 #include<cstdio>
 2 #include<iostream>
 3 #define ll long long
 4 #define MAXN 50010
 5 using namespace std;
 6 int t=1,n,a[MAXN];
 7 ll ans=0;
 8 inline void read(int&x) {
 9     x=0;char c=getchar();
10     while(c>‘9‘||c<‘0‘) c=getchar();
11     while(c>=‘0‘&&c<=‘9‘) x=10*x+c-48,c=getchar();
12 }
13 inline void go(int k) {
14     int temp=a[k-1]+a[k];
15     ans+=temp;
16     for(int i=k;i<t-1;i++) a[i]=a[i+1];
17     t--;
18     int j=0;
19     for(j=k-1;j>0&&a[j-1]<temp;j--)
20       a[j]=a[j-1];
21     a[j]=temp;
22     while(j>=2&&a[j]>=a[j-2]) {
23         int p=t-j;
24         go(j-1);
25         j=t-p;
26     }
27 }
28 int main() {
29     read(n);
30     for(int i=0;i<n;i++) read(a[i]);
31     for(int i=1;i<n;i++) {
32         a[t++]=a[i];
33         while(t>=3&&a[t-3]<=a[t-1]) go(t-2);
34     }
35     while(t>1) go(t-1);
36     printf("%lld\n",ans);
37     return 0;
38 } 

时间: 2025-01-19 21:33:55

2298 石子合并 2008年省队选拔赛山东的相关文章

[08山东省选]2298 石子合并

2298 石子合并 2008年省队选拔赛山东 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 在一个操场上摆放着一排N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分. 试设计一个算法,计算出将N堆石子合并成一堆的最小得分. 输入描述 Input Description 第一行是一个数N. 以下N行每行一个数A,表示石子数目. 输出描述 O

石子合并(四边形不等式优化)

题目大意很简单,和普通的石子合并过程没有区别,只是花费变成了一个多项式,若连续的任意个石子权值和为x,那么代价变为F(x) = sigma(a[i] * x^i),求将n堆石子合并为一队的最小花费. 对于暴力的做法,复杂度是O(n^3)的,所以要优化 我们知道当a, b, c, d(a <= b < c <= d)当有cost[a][c] + cost[b][d] <= cost[a][d] + cost[b][c] 时,我们称其满足四边形不等式,设p[i][j]表示当区间[i,

BZOJ 3229: [Sdoi2008]石子合并

3229: [Sdoi2008]石子合并 时间限制: 3 Sec  内存限制: 128 MB提交: 497  解决: 240[提交][][] 题目描述 在一个操场上摆放着一排N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分. 试设计一个算法,计算出将N堆石子合并成一堆的最小得分. 输入 第一行是一个数N. 以下N行每行一个数A,表示石子数目. 输出 共一个数,即N堆石子合并成一堆的最小得分. 样例输入 4 1 1 1 1 样

四边形不等式优化DP——石子合并问题 学习笔记

好方啊马上就要区域赛了连DP都不会QAQ 毛子青<动态规划算法的优化技巧>论文里面提到了一类问题:石子合并. n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分. 求出将n堆石子合并成一堆的最小得分和最大得分以及相应的合并方案. 设m[i,j]表示合并d[i..j]所得到的最小得分. 状态转移方程: 总的时间复杂度为O(n3). [优化方案] 四边形不等式: m[i,j]满足四边形不等式 令s[i,j]=max{k | m[

zjnu1181 石子合并【基础算法?动态规划】——高级

Description 在操场上沿一直线排列着 n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分.允许在第一次合并前对调一次相邻两堆石子的次序. 计算在上述条件下将n堆石子合并成一堆的最小得分. Input 输入数据共有二行,其中,第1行是石子堆数n≤100: 第2行是顺序排列的各堆石子数(≤20),每两个数之间用空格分隔. Output 输出合并的最小得分. Sample Input 3 2 5 1 Sample Out

洛谷 P1880 石子合并

题目描述 在一个圆形操场的四周摆放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

P1880 石子合并

P1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分. 输入输出格式 输入格式: 数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数. 输出格式: 输出共2行,第1行为最小得分,第2行为最大得分. 输入输出样例 输入样例#1: 4 4 5 9 4 输出样例#1:

luogu P1880 石子合并

题目描述 在一个园形操场的四周摆放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 区间动态规

洛谷1880 石子合并

P1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分. 输入输出格式 输入格式: 数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数. 输出格式: 输出共2行,第1行为最小得分,第2行为最大得分. 输入输出样例 输入样例#1: 4 4 5 9 4 输出样例#1: