Description

There is an old stone game.At the beginning of the game the player picks n(1<=n<=50000) piles of stones in a line. The goal is to merge the stones in one pile observing the following rules: 
At each step of the game,the player can merge two adjoining piles to a new pile.The score is the number of stones in the new pile. 
You are to write a program to determine the minimum of the total score. 

Input

The input contains several test cases. The first line of each test case contains an integer n, denoting the number of piles. The following n integers describe the number of stones in each pile at the beginning of the game. 
The last test case is followed by one zero. 

Output

For each test case output the answer on a single line.You may assume the answer will not exceed 1000000000.

Sample Input

1
100
3
3 4 3
4
1 1 1 1
0

Sample Output

0
17
8
解题思路:GarsiaWachs算法,时间复杂度为O(n^2)。它的算法步骤如下:设序列是stone[1~n],从左往右找一个满足stone[k-1]<=stone[k+1]的k,然后合并stone[k-1]和stone[k]为tmp,再从位置k-1向左找一个最大的j,使其满足stone[j]>tmp,并将tmp插到j的后面。一直重复,直到将所有石子合并。在这个过程中,可以假设stone[0]和stone[n+1]是+∞的。
举个例子:186 64 35 32 103
∵35<103,∴第一次满足条件的k下标(下标从0开始计算)为3,我们先把35和32删除,得到它们的和67,并向前寻找一个第一个大于67的数,把67插入到它后面,得到:186 67 64 103,现在由5个数变为4个数了,继续同样的操作:186 131 103,则k=2(别忘了,设stone[0]和stone[n+1]等于+∞)此时的序列为234 186,最后一次合并便得到420。最终的答案呢?就是各次合并的代价之和,即420+234+131+67=852。
基本思想是通过树的最优性得到一个节点间深度的约束,之后证明操作一次之后的解可以和原来的解一一对应,并保证节点移动之后它所在的深度不会改变。具体实现这个算法需要一点技巧,精髓在于不停快速寻找最小的k,即维护一个“2-递减序列”朴素的实现的时间复杂度是O(n*n),但可以用一个平衡树来优化,使得最终复杂度为O(nlogn)。
(转)补证:问题分析:(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[k-1]<=stone[k+1]最小的k, 合并stone[k-1]+stone[k]为tmp, 接着往前面找满足条件stone[j]>tmp, 把tmp值插入stone[j]的后面(数组的右边). 循环这个过程一直到只剩下一堆石子结束。
(3)、为什么要将tmp插入stone[j]后面, 可以理解为(1)的情况,从stone[j+1]到stone[k-2]看成一个整体stone[mid],那么对于stone[j],stone[mid], tmp,必有tmp<stone[j],∴不管怎样都是stone[mid]和tmp先合并, 即将tmp值插入stone[j]的后面是不影响结果的。
AC代码(141ms):
 #include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=;
const int inf=0x7fffffff;//2147483647
int n,m,t,ans,stone[maxn];
void dfs(int k){
int tmp=stone[k-]+stone[k];
ans+=tmp;t--;
for(int i=k;i<t;++i)stone[i]=stone[i+];//元素左移,表示删掉了一个元素
int j=;k--;
for(j=k;stone[j-]<tmp;--j)stone[j]=stone[j-];//元素右移,找到第一个满足条件的j
stone[j]=tmp;//将tmp插到j后面
while(j>=3&&stone[j-]<=stone[j]){//继续向前查找是否还有满足条件的情况
int d=t-j;//保存当前t离操作点的距离d
dfs(j-);//合并第j-1堆和第j-2堆石子
j=t-d;//设置新的操作点j
}
}
int main(){
while(~scanf("%d",&n)&&n){
for(int i=;i<=n;++i)scanf("%d",&stone[i]);
t=,ans=;stone[]=stone[n+]=inf;
for(int i=;i<=n;++i){
stone[t++]=stone[i];
while(t>&&stone[t-]<=stone[t-])dfs(t-);//表示当前至少有3堆石子,并且满足stone[k-1]<=stone[k+1],k=t-2,就合并第t-3和第t-2堆石子
}
while(t>)dfs(t-);//如果剩下的堆数至少为3-1=2堆,则继续合并,直至剩下一堆石子
printf("%d\n",ans);
}
return ;
}
												

题解报告:poj 1738 An old Stone Game(区间dp)的更多相关文章

  1. POJ 1651:Multiplication Puzzle(区间DP)

    http://poj.org/problem?id=1651 题意:给出n个数字,每取中间一个数,就会使得权值加上中间这个数和两边的乘积,求取剩两个数最少的权值是多少. 思路:区间dp. 一开始想了挺 ...

  2. [08山东省选]2298 石子合并 即POJ 1738 An old Stone Game

    2298 石子合并 2008年省队选拔赛山东  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 在 ...

  3. POJ 1738 An old Stone Game(石子合并 经典)

    An old Stone Game Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 3672   Accepted: 1035 ...

  4. 【题解】POJ 3417 Network(倍增求LCA+DP+树上差分)

    POJ3417:http://poj.org/problem?id=3417 思路 我们注意到由“主要边”构成一颗树 “附加边”则是非树边 把一条附加边(x,y)加入树中 会与树上x,y之间构成一个环 ...

  5. poj 1694 An Old Stone Game 树形dp

    //poj 1694 //sep9 #include <iostream> #include <algorithm> using namespace std; const in ...

  6. POJ 2671 Jimmy's Bad Day题解(很详细很友好,类似区间dp)

    有问题的话欢迎在评论区提出 题意: 题目链接 你是一个送快递的,现在给你一个环,环的边有权值,代表走这条边所花的时间,每个点代表一个地点,点有点权,代表这个点上有多少货物需要你送.初始时间\(t=0\ ...

  7. 题解报告:hdu 1520 Anniversary party(树形dp入门)

    Problem Description There is going to be a party to celebrate the 80-th Anniversary of the Ural Stat ...

  8. POJ 题目1141 Brackets Sequence(区间DP记录路径)

    Brackets Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 27793   Accepted: 788 ...

  9. POJ 题目3280 Cheapest Palindrome(区间DP)

    Cheapest Palindrome Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7148   Accepted: 34 ...

随机推荐

  1. Android Camera系统深入理解

    1. Android Camera系统架构 http://blog.csdn.net/myarrow/article/details/8489674

  2. ARC机制之__strong具体解释

    ARC机制之__strong具体解释 __strong  解析: 默认情况下,一个指针都会使用 __strong 属性,表明这是一个强引用.这意味着,仅仅要引用存在,对象就不能被销毁.这是一种所期望的 ...

  3. debian iptables持久化

    1 保存iptables iptables-save > /etc/iptables.rules   2 创建启动文件 touch /etc/network/if-pre-up.d/iptabl ...

  4. top load average

    负载均值 等待运行的进程数

  5. C语言文件读写Demo

    CIODemo.c #include <stdio.h> #include <time.h> #define INPUT_BUFFER_SIZE 100 * 1024 int ...

  6. 【POJ 1159】Palindrome

    [POJ 1159]Palindrome 近期各种题各种奇葩思路已经司空见惯了...又新出个滚动数组= = 该题另一点须要知道 最少须要补充的字母数 = 原序列S的长度 - S和S'的最长公共子串长度 ...

  7. uCOS-II模拟(VS2010&WIN32)

    转自http://www.amobbs.com/thread-5462878-1-1.html 自学uCOS-II源码,在论坛上上看到大神在WIN7 Visual Studio 2010环境下调试uC ...

  8. SQL Server 数据库备份策略,第一周运行失败的原因

    一般生产库,采用 每10分钟备份Log,每天备份Diff,每周备份Full的策略. 同时存在异地备份.异地备份可使用SQL Server本身的cmdshell存储过程,调用系统命令. 在为新数据库,建 ...

  9. linux初级学习笔记二:linux操作系统及常用命令,文件的创建与删除和命名规则,命令行展开以及linux中部分目录的作用!(视频序号:02_3)

    本节学习的命令:tree,mkdir,rmdir,touch,stat,rm 本节学习的技能:Linux中主要的目录作用以及特殊的目录文件: 文件的命名规则,命令行展开: 文件的创建与删除: Linu ...

  10. codeforces 414C C. Mashmokh and Reverse Operation(归并排序求逆序对)

    题目链接: C. Mashmokh and Reverse Operation time limit per test 4 seconds memory limit per test 512 mega ...