HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)
题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小。一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0。
析:DP状态方程很容易想出来,dp[i][j] 表示前 j 个数分成 i 组。但是复杂度是三次方的,肯定会超时,就要对其进行优化。
有两种方式,一种是斜率对其进行优化,是一个很简单的斜率优化
dp[i][j] = min{dp[i-1][k] - w[k] + sum[k]*sum[k] - sum[k]*sum[j]} + w[j] (i-1<=k<j)。sum[i]表示前i个数之和,w[i]表示前i个数分成一组的价值。
第二种方式就是四边形不等式进行优化,
dp[i][j] = min{dp[i-1][k] + w[k+1][j] } w[i][j] 表示第 i 个数到第 j 个数的价值和。
代码如下:
斜率优化:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e16;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e3 + 10;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
} int dp[maxn][maxn], w[maxn];
int a[maxn], sum[maxn];
int q[maxn]; int getUP(int i, int j, int k){
return dp[i-1][j] - w[j] + sum[j] * sum[j] - (dp[i-1][k] - w[k] + sum[k] * sum[k]);
} int getDOWN(int i, int j){
return sum[i] - sum[j];
} int getDP(int i, int j){
return dp[i-1][j] - w[j] + sum[j] * sum[j];
} int main(){
while(scanf("%d %d", &n, &m) == 2 && n+m){
for(int i = 1; i <= n; ++i){
scanf("%d", a+i);
sum[i] = sum[i-1] + a[i];
w[i] = w[i-1] + a[i] * sum[i-1];
dp[0][i] = w[i];
}
for(int i = 1; i <= m; ++i){
int fro = 0, rear = 0;
q[++rear] = 0;
for(int j = 1; j <= n; ++j){
while(fro + 1 < rear && getUP(i, q[fro+2], q[fro+1]) <= sum[j]*getDOWN(q[fro+2], q[fro+1])) ++fro;
dp[i][j] = getDP(i, q[fro+1]) + w[j] - sum[j] * sum[q[fro+1]];
while(fro + 1 < rear && getUP(i, j, q[rear])*getDOWN(q[rear], q[rear-1]) <= getUP(i, q[rear], q[rear-1])*getDOWN(j, q[rear])) --rear;
q[++rear] = j;
}
}
printf("%d\n", dp[m][n]);
}
return 0;
}
四边形不等式优化:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e16;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e3 + 10;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
} LL dp[maxn][maxn], w[maxn][maxn];
int a[maxn], sum[maxn], s[maxn][maxn]; int main(){
while(scanf("%d %d", &n, &m) == 2 && n+m){
for(int i = 1; i <= n; ++i){
scanf("%d", a+i);
sum[i] = sum[i-1] + a[i];
}
for(int i = 1; i <= n; ++i){
w[i][i] = 0;
for(int j = i+1; j <= n; ++j)
w[i][j] = w[i][j-1] + a[j] * (sum[j-1]-sum[i-1]);
} memset(s, 0, sizeof s);
for(int i = 0; i <= m; ++i)
fill(dp[i], dp[i]+n+1, LNF);
for(int i = 1; i <= n; ++i) dp[0][i] = w[1][i];
for(int i = 1; i <= m; ++i){
dp[0][i] = 0;
s[i][n+1] = n;
for(int j = n; j >= i; --j)
for(int k = s[i-1][j]; k <= s[i][j+1]; ++k)
if(dp[i][j] > dp[i-1][k] + w[k+1][j]){
dp[i][j] = dp[i-1][k] + w[k+1][j];
s[i][j] = k;
}
}
printf("%I64d\n", dp[m][n]); }
return 0;
}
HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)的更多相关文章
- 【转】斜率优化DP和四边形不等式优化DP整理
(自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...
- hdu 2829 Lawrence(斜率优化DP)
题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...
- 区间DP的四边形不等式优化
今天上课讲DP,所以我学习了四边形不等式优化(逃 首先我先写出满足四边形不等式优化的方程:
- 区间dp之四边形不等式优化详解及证明
看了那么久的四边形不等式优化的原理,今天终于要写一篇关于它的证明了. 在平时的做题中,我们会遇到这样的区间dp问题 它的状态转移方程形式一般为dp[i][j]=min(dp[i][k]+dp[k+1] ...
- 『一维线性dp的四边形不等式优化』
四边形不等式 定义:设\(w(x,y)\)是定义在整数集合上的的二元函数,若对于定义域上的任意整数\(a,b,c,d\),在满足\(a\leq b\leq c \leq d\)时,都有\(w(a,d) ...
- HDU 2829 - Lawrence - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2829 T. E. Lawrence was a controversial figure during ...
- hdu 2829 Lawrence(四边形不等式优化dp)
T. E. Lawrence was a controversial figure during World War I. He was a British officer who served in ...
- HDU.2829.Lawrence(DP 斜率优化)
题目链接 \(Description\) 给定一个\(n\)个数的序列,最多将序列分为\(m+1\)段,每段的价值是这段中所有数两两相乘的和.求最小总价值. \(Solution\) 写到这突然懒得写 ...
- HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化
HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...
随机推荐
- QLCDNumber设置背景色和显示数字颜色【转载】
http://www.qtcn.org/bbs/read-htm-tid-55176.html //LCD时间显示 QLCDNumber *m_pLcdTime = new QLCDNumber ...
- (转)App工程结构搭建:几种常见Android代码架构分析
关于Android架构,因为手机的限制,目前我觉得也确实没什么大谈特谈的,但是从开发的角度,看到整齐的代码,优美的分层总是一种舒服的享受的. 从艺术的角度看,其实我们是在追求一种美. 本文先分析几个当 ...
- MySQL-5.7中InnoDB表数据文件存储位置
学习地址:https://www.cnblogs.com/tongxiaoda/p/7874535.html
- mysql + unidac 使用事务例子
//备注:mysql必须是使用innoDB引擎才支持事务功能,否则以下事务相关代码将失效.//SQL SERVER和Oracle还没试,明天回公司试了再发代码.procedure TForm1.btn ...
- mysql导入导出表结构
mysql导入导出表结构 导出整个库的表结构如下:mysqldump -uroot -p -d databasename > createtab.sql 如果只想导出表: test1,test2 ...
- 【转】Jmeter笔记:响应断言详解
平时我们使用jmeter进行性能测试时,经常会用到断言.jmeter提供了很多种断言,本来想全都写一下,但发现每一个断言里面的东西都很多,所以就先写一下我们经常使用的响应断言. 第一次在cnblog上 ...
- Excel开发学习笔记:根据工作表worksheet内容控制按钮的状态
开发环境基于VSTO,具体配置:visual studio 2010,VB .Net,excel 2007,文档级别的定制程序. 在Ribbon工具栏中有2个功能按钮,它们是否可用取决于workshe ...
- 学习笔记::fft
上次学fft还是5月份,昨天发现已经忘记怎么推导了,代码也看不懂了,就又学习了一发,大概是看menci的博客 0.fft可以进行多项式乘法,朴素的乘法跟手算一样是O(n^2),fft可以通过分治做到n ...
- Tulpar-web渗透小工具
首先git clone一下,项目地址:https://github.com/anilbaranyelken/tulpar 下载完后打开文件 然后安装所需的Python模块 安装完成后先看一下帮助 命令 ...
- 大杀器TheFatRat
项目地址:https://github.com/Screetsec/TheFatRat 安装TheFatRat root@sch01ar:/sch01ar# git clone https://git ...