合并石子(区间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堆石子并成为一堆.合并的过程只能每次将相邻的两堆 ...
随机推荐
- 关于html5 video的连续播放
<!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- H5白屏问题
前言 前阵子弄了灰度环境,H5这边需要给灰度环境的接口加上Cookie,配置的期间遇到一些Cookie问题以及白屏在此记录下 1.H5请求接口带不上Cookie 解决方法:前端使用了 webpack ...
- JUC并发包基本使用
一.简介 传统的Java多线程开发中,wait.notify.synchronized等如果不注意使用的话,很容易引起死锁.脏读问题.Java1.5 版本开始增加 java.util.concurre ...
- 通过css样式给表格tbody加垂直滚动条
tbody加滚动条实现思路: 1,把tbody设置成display:block,然后就对其高度设置一个固定值,overflow设置成auto. 2,把thead的tr设置成display:block. ...
- C# 给DataTable去重
using System; using System.Data; namespace DelegateTest { public class Program { public static void ...
- nodejs http服务器简单搭建
var http = require('http') // 1. 创建 Server var server = http.createServer() // 2. 监听 request 请求事件,设置 ...
- vue+element ui 滚动加载
<div id="app"> <div class="infinite-list-wrapper" style="overflow: ...
- 03scikit-learn非监督学习
In [1]: from sklearn.decomposition import PCA from sklearn.datasets import load_iris pca = PCA(n_com ...
- [sqlmap源码阅读] 数据库识别
通过网页返回的数据库错误信息识别网站所有数据库类型,用到的正则表达式及支持识别的数据库类型,这些信息以xml文件的形式存在,使用 sax 解析xml.
- bzoj4002 [JLOI2015]有意义的字符串 特征根+矩阵快速幂
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4002 题解 神仙题. 根据下面的一个提示: \[ b^2 \leq d \leq (b+1)^ ...