题解报告:poj 1738 An old Stone Game(区间dp)
Description
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 last test case is followed by one zero.
Output
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)的更多相关文章
- POJ 1651:Multiplication Puzzle(区间DP)
http://poj.org/problem?id=1651 题意:给出n个数字,每取中间一个数,就会使得权值加上中间这个数和两边的乘积,求取剩两个数最少的权值是多少. 思路:区间dp. 一开始想了挺 ...
- [08山东省选]2298 石子合并 即POJ 1738 An old Stone Game
2298 石子合并 2008年省队选拔赛山东 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 在 ...
- POJ 1738 An old Stone Game(石子合并 经典)
An old Stone Game Time Limit: 5000MS Memory Limit: 30000K Total Submissions: 3672 Accepted: 1035 ...
- 【题解】POJ 3417 Network(倍增求LCA+DP+树上差分)
POJ3417:http://poj.org/problem?id=3417 思路 我们注意到由“主要边”构成一颗树 “附加边”则是非树边 把一条附加边(x,y)加入树中 会与树上x,y之间构成一个环 ...
- poj 1694 An Old Stone Game 树形dp
//poj 1694 //sep9 #include <iostream> #include <algorithm> using namespace std; const in ...
- POJ 2671 Jimmy's Bad Day题解(很详细很友好,类似区间dp)
有问题的话欢迎在评论区提出 题意: 题目链接 你是一个送快递的,现在给你一个环,环的边有权值,代表走这条边所花的时间,每个点代表一个地点,点有点权,代表这个点上有多少货物需要你送.初始时间\(t=0\ ...
- 题解报告:hdu 1520 Anniversary party(树形dp入门)
Problem Description There is going to be a party to celebrate the 80-th Anniversary of the Ural Stat ...
- POJ 题目1141 Brackets Sequence(区间DP记录路径)
Brackets Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 27793 Accepted: 788 ...
- POJ 题目3280 Cheapest Palindrome(区间DP)
Cheapest Palindrome Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7148 Accepted: 34 ...
随机推荐
- oracle的shared、dedicated模式解析
主要參考文档:http://www.itpub.net/thread-1714191-1-1.html Oracleh有两种server模式shared mode和dedicated mode. De ...
- 【读书笔记】iOS-GCD-用法
代码: -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { dispatch_async(dispatch_get_gl ...
- GPG key
Creating GPG Keys - Fedora Project Wiki https://fedoraproject.org/wiki/Creating_GPG_Keys
- Provided Maven Coordinates must be in the form 'groupId:artifactId:version'.
[hadoop@hadoop1 bin]$ ./spark-shell --packages org.mongodb.spark:mongo-spark-connector_2.10-2.2.1 Ex ...
- bind_ip
https://docs.mongodb.com/manual/reference/configuration-options/index.html 192.168.2.* --23T10:: I C ...
- filter、servlet、interceptor的执行顺序
1. Filter可认为是Servlet的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.它与Servlet的区别在于:它不能 ...
- 获取Android设备无线和以太网MAC地址
package com.raycloud.wolf.blogformac; import android.net.wifi.WifiManager; import android.support.v7 ...
- NSString类的方法实现
创建一个新字符串并将其设置为 path 指定的文件的内容,使用字符编码enc,在error上返回错误 + (id)stringWithContentsOfURL:(NSURL *)url encodi ...
- Jmeter性能测试-GC相关
1.GC相关 HotSpot虚拟机将其物理上划分为两个–新生代(young generation)和老年代(old generation).新生代(Young generation): 绝大多数最新被 ...
- ElementUI的Upload上传,配合七牛云储存图片
七牛云服务器的储存区域 存储区域 地域简称 上传域名 华东 z0 服务器端上传:http(s)://up.qiniup.com 华东 z0 客户端上传: http(s)://upload.qiniup ...