题解报告:NYOJ #737 石子合并(一)(区间dp)
描述
有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开输出输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
7
13 7 8 16 21 4 18
样例输出
9
239
解题思路:经典区间dp!石子合并问题!定义dp[i][j]表示将区间[i,j]合并后得到的最小代价,易想到相邻先两两合并,再三三合并....,直到将整个区间合并完成,dp[1][n]就是要求的最小代价。
状态转移方程为dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]),其中sum[j]-sum[i-1](预处理前缀和)为将区间[i,j]合并得到的代价,k为断点的枚举。时间复杂度为O(n^3)。
AC代码一(340ms):
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int n,a[maxn],sum[maxn],dp[maxn][maxn];
int main(){
while(~scanf("%d",&n)){
memset(dp,0x3f,sizeof(dp));
memset(sum,,sizeof(sum));
for(int i=;i<=n;++i)scanf("%d",&a[i]),sum[i]=sum[i-]+a[i],dp[i][i]=;//初始状态dp[i][i]表示当前每一堆的代价为0
for(int len=;len<=n;++len){//区间长度
for(int i=;i<=n-len;++i){//区间起点
int j=i+len;//区间终点
for(int k=i;k<j;++k)//断点k把(i,j)分成2堆,dp[i][j]为原来两堆各自的代价和再加上合并的两堆得到的代价之和
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+][j]+sum[j]-sum[i-]);
}
}
printf("%d\n",dp[][n]);
}
return ;
}
AC代码二(0ms):GarsiaWachs算法,时间复杂度为0(n^2)。
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=;
const int inf=0x7fffffff;//
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)){
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 ;
}
题解报告:NYOJ #737 石子合并(一)(区间dp)的更多相关文章
- nyoj 737 石子合并(区间DP)
737-石子合并(一) 内存限制:64MB 时间限制:1000ms 特判: No通过数:28 提交数:35 难度:3 题目描述: 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为 ...
- nyoj 737 石子合并 经典区间 dp
石子合并(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆 ...
- nyoj 737 石子合并(一)。区间dp
http://acm.nyist.net/JudgeOnline/problem.php?pid=737 数据很小,适合区间dp的入门 对于第[i, j]堆,无论你怎么合并,无论你先选哪两堆结合,当你 ...
- nyoj 737 石子合并 http://blog.csdn.net/wangdan11111/article/details/45032519
http://blog.csdn.net/wangdan11111/article/details/45032519 http://acm.nyist.net/JudgeOnline/problem. ...
- NYOJ 737 石子合并(一)
题意 排成一排的石子,每次合并相邻两堆并由一定的代价,求合并成一堆的最小代价 解法 区间dp 枚举长度 dp[i,j]表示合并石子堆编号从i到j为一堆所需的最小代价(这个题目的代价是sum(i..j) ...
- 石子合并2——区间DP【洛谷P1880题解】
[区间dp让人头痛……还是要多写些题目练手,抽空写篇博客总结一下] 这题区间dp入门题,理解区间dp或者练手都很妙 ——题目链接—— (或者直接看下面) 题面 在一个圆形操场的四周摆放N堆石子,现要将 ...
- 洛谷P1880 石子合并(区间DP)(环形DP)
To 洛谷.1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1 ...
- 直线石子合并(区间DP)
石子合并 时间限制:1000 ms | 内存限制:65535 KB 描述有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费 ...
- CH5301 石子合并【区间dp】
5301 石子合并 0x50「动态规划」例题 描述 设有N堆沙子排成一排,其编号为1,2,3,…,N(N<=300).每堆沙子有一定的数量,可以用一个整数来描述,现在要将这N堆沙子合并成为一堆, ...
随机推荐
- Vs2012在Linux开发中的应用(6):改写Makefile项目的Build过程
MSBUILD的编译过程实际上是依据一系列的targets文件定义的.当我们在IDE运行生成.批生成.清理命令的时候.VS会查找这些命令相应的Task并运行它,以下我们逐个分析这个过程. 当运行生成操 ...
- JAVA学习之 Model2中的Servlet与.NET一般处理程序傻傻分不清楚
时隔多日,多日合适吗,应该是时隔多月.我又想起了一般处理程序.这都是由于近期在实现的DRP系统中经经常使用到jsp+servlet达到界面与逻辑的分离.servlet负责处理从jsp传回的信息:每当这 ...
- UVA - 11019 Matrix Matcher hash+KMP
题目链接:传送门 题解: 枚举每一行,每一行当中连续的y个我们hash 出来 那么一行就是 m - y + 1个hash值,形成的一个新 矩阵 大小是 n*(m - y + 1), 我们要找到x*y这 ...
- JavaScript and ActionScript3
接触JavaScript和ActionScript3也有一段时间了,它们都是应用比较广泛的脚本语言,经过这几年的工作和学习,静下来的时候想总结一些东西,作为技术上的沉淀以及培训所用,所以就有了这篇文章 ...
- android 中的常用组件
gradle gradle 是个啥,一开始我也没弄清,官方解释是: Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具 那么Apache Ant和Apache ...
- searchkick HasMany Associations | index related model fields
Project < ActiveRecord::Base searchkick has_many :categories_has_projects has_many :categories, t ...
- 计算机学院大学生程序设计竞赛(2015’12)Bitwise Equations
Bitwise Equations Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- 【Java】DateUtil(1)
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...
- 第三届蓝桥杯C++B组省赛
1.微生物增值 2.古堡算式 3.海盗比酒量 4.奇怪的比赛 5.方阵旋转 6.大数乘法 7.放棋子 8.密码发生器 9.夺冠概率 10.取球博弈
- ping 中的“TTL"是什么意思
简单来说就是表示一个数据包在网络中可以跳跃的结点数据,当该数据为零时本数据包将被抛弃 详细解释看以下引用: TTL (although named as "time" to liv ...