合并石子(区间DP)
有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动相邻的2堆石子合并,合并花费为新合成的一堆石子的数量。求将这N堆石子合并成一堆的总花费最小。
区间DP思想:现在小区间进行DP得到最优解,然后再利用小区间的最优解组合并求大区间的最优解。(需要从小到大枚举所有可能的区间)
代码(没提交过,不过应该正确):
include
using namespace std;
const int maxn1=300;
int main()
{
int n,a[maxn1]={0},sum[maxn1]={0};
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],sum[i]=a[i]+sum[i-1]; //前缀和
int dp[maxn1][maxn1]={0}; //dp[i][j]表示区间[i,n]的最小花费
for(int len=1;len<n;len++) //枚举所有可能的区间
{
for(int i=1;i<=n-len;i++)
{
dp[i][i+len]=INT_MAX;
for(int k=i;k<i+len;k++)
dp[i][i+len]=min(dp[i][i+len],dp[i][k]+dp[k+1][i+len]+sum[i+len]-sum[i-1]);
}
}
cout<<dp[1][n]<<endl;
return 0;
}
这样写很容易理解,但复杂度为O(n^3),基本最多只能计算250堆石子。
在网上看了一个平行四边形对区间DP的优化,复杂度基本可以维持在O(n^2),但是我却始终不理解其原理,不过大概按葫芦画瓢,写了一个(并注释了与之前O(n^3)的不同):
include
using namespace std;
const int maxn1=3000;
int main()
{
int n,a[maxn1]={0},sum[maxn1]={0},s[maxn1][maxn1];
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],sum[i]=a[i]+sum[i-1];
for(int i=1;i<=n;i++) //多加
s[i][i]=i; //多加 (记录区间最优解的位置)
int dp[maxn1][maxn1]={0};
for(int len=1;len<n;len++)
{
for(int i=1;i<=n-len;i++)
{
dp[i][i+len]=INT_MAX;
for(int k=s[i-1][i+len];k<=s[i+1][i+len];k++) //改变
if(dp[i][k]+dp[k+1][i+len]+sum[i+len]-sum[i-1]<dp[i][i+len]) //改变
{
dp[i][i+len]=dp[i][k]+dp[k+1][i+len]+sum[i+len]-sum[i-1]; //改变
s[i][i+len]=k; //改变
}
}
}
cout<<dp[1][n]<<endl;
return 0;
}
合并石子(区间DP)的更多相关文章
- 洛谷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堆沙子合并成为一堆, ...
- zjnu 1181 石子合并(区间DP)
Description 在操场上沿一直线排列着 n堆石子. 现要将石子有次序地合并成一堆.规定每次仅仅能选相邻的两堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分.同意在第一次合并前对调一 ...
- nyoj 737 石子合并(区间DP)
737-石子合并(一) 内存限制:64MB 时间限制:1000ms 特判: No通过数:28 提交数:35 难度:3 题目描述: 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为 ...
- 石子合并2——区间DP【洛谷P1880题解】
[区间dp让人头痛……还是要多写些题目练手,抽空写篇博客总结一下] 这题区间dp入门题,理解区间dp或者练手都很妙 ——题目链接—— (或者直接看下面) 题面 在一个圆形操场的四周摆放N堆石子,现要将 ...
- 石子合并问题 /// 区间DP oj2025
Description 在一个圆形操场的四周摆放着n堆石子.现要将石子有次序地合并成一堆. 规定每次只能选相邻的两堆石子合并成新的一堆,并将新得的这堆石子数记为该次合并的得分. 试设计一个算法,计算出 ...
- 石子合并 (区间DP)
一.试题在一个园形操场的四周摆放N堆石子(N≤100),现要将石子有次序地合并成一堆.规定每次仅仅能选相邻的两堆合并成新的一堆,并将新的一堆的石子数.记为该次合并的得分.编一程序.由文件读入堆数N及每 ...
- 合并傻子//区间dp
P1062 合并傻子 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 从前有一堆傻子,钟某人要合并他们~但是,合并傻子是要掉RP的...... 描述 在一个园 ...
- nyoj 737 石子合并 经典区间 dp
石子合并(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆 ...
随机推荐
- [Codeforces 1199D]Welfare State(线段树)
[Codeforces 1199D]Welfare State(线段树) 题面 给出一个长度为n的序列,有q次操作,操作有2种 1.单点修改,把\(a_x\)修改成y 2.区间修改,把序列中值< ...
- ex2、逻辑回归
介绍: 在本练习中,您将实现逻辑回归,并将其应用于两个不同的数据集.在开始编程练习之前,我们强烈要求建议观看视频讲座并完成相关主题的问题.要开始练习,您需要下载起始代码并将其内容解压缩到要完成练习的目 ...
- Spring之使用注解实例化Bean并注入属性
1.准备工作 (1)导入jar包 除了上篇文章使用到的基本jar包外,还得加入aop的jar包,所有jar包如下 所需jar包 (2)配置xml <?xml version="1.0& ...
- 模板 - 线性递推BM
模数是998244353的话好像NTT可以更快. #include<bits/stdc++.h> using namespace std; typedef long long ll; co ...
- Unity3D 优化
用UNITY开发手机游戏,背景图片和UI图片显示的比PC机上模糊非常多,怎么解决??在unity里选中资源 1.TextureType 改成 Advanced2.NonPower of 2 改成 no ...
- 游戏服务端pomelo完整安装配置过程
版权声明:本文为博主原创文章,转载或又一次发表请先与我联系. https://blog.csdn.net/jonahzheng/article/details/27658985 游戏服务端pomelo ...
- linux下docker启动nginx无法访问80端口
问题: Linux安装了docker,docker启动了一个nginx容器,通过 80 端口无法正常访问 故障排查: 1.检查 nginx 容器启动的命令或者yaml文件,查看是否有跟本机端口进行绑定 ...
- C# Lodop与C-Lopdop选择打印机
原文:https://www.cnblogs.com/huaxie/p/9766886.html https://www.cnblogs.com/huaxie/p/10857490.html http ...
- Antd-react-mobile项目学习中遇到的问题记录(持续更新)
1.Error:The "injectBabelPlugin" helper has been deprecated as of v2.0. You can use customi ...
- Thymeleaf运算符和表达式
字符串拼接 方式一: <span th:text="'当前是第'+${page}+'页 ,共'+${page}+'页'"></span> 方式二: 使用&q ...