题意:给定 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)的更多相关文章

  1. 【转】斜率优化DP和四边形不等式优化DP整理

    (自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...

  2. hdu 2829 Lawrence(斜率优化DP)

    题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...

  3. 区间DP的四边形不等式优化

    今天上课讲DP,所以我学习了四边形不等式优化(逃 首先我先写出满足四边形不等式优化的方程:

  4. 区间dp之四边形不等式优化详解及证明

    看了那么久的四边形不等式优化的原理,今天终于要写一篇关于它的证明了. 在平时的做题中,我们会遇到这样的区间dp问题 它的状态转移方程形式一般为dp[i][j]=min(dp[i][k]+dp[k+1] ...

  5. 『一维线性dp的四边形不等式优化』

    四边形不等式 定义:设\(w(x,y)\)是定义在整数集合上的的二元函数,若对于定义域上的任意整数\(a,b,c,d\),在满足\(a\leq b\leq c \leq d\)时,都有\(w(a,d) ...

  6. HDU 2829 - Lawrence - [斜率DP]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2829 T. E. Lawrence was a controversial figure during ...

  7. hdu 2829 Lawrence(四边形不等式优化dp)

    T. E. Lawrence was a controversial figure during World War I. He was a British officer who served in ...

  8. HDU.2829.Lawrence(DP 斜率优化)

    题目链接 \(Description\) 给定一个\(n\)个数的序列,最多将序列分为\(m+1\)段,每段的价值是这段中所有数两两相乘的和.求最小总价值. \(Solution\) 写到这突然懒得写 ...

  9. HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化

    HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...

随机推荐

  1. 初上dubbo

    编译异常 no groovy library is defined for module http://blog.csdn.net/lu_wei_wei/article/details/7601968 ...

  2. 双击 cui

    //改变属性块的双击事件 //将菜单文件中的双击改一下,退出时还原文件 acad.bak.cui 改这个名字 每次用这个更新为新的 acad.cui进行修改 //退出时再用 acad.bak.cui还 ...

  3. hdu 5730 Shell Necklace——多项式求逆+拆系数FFT

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5730 可以用分治FFT.但自己只写了多项式求逆. 和COGS2259几乎很像.设A(x),指数是长度,系数 ...

  4. 提升Apache网站访问速度的优化方法

    Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一. 在Apache服务器上怎样优化才能提高 ...

  5. 重装系统, i tell you

    博客网站: https://blog.csdn.net/ca1m0921/article/details/79313050 装机例子1: http://www.xitongcheng.com/jiao ...

  6. [三卷天书]ajax请求时接收到乱码的处理方案

    $.ajax({ url: "getmore.ashx", type: "post", dataType: "text", data: { ...

  7. 【原创】 HBase 配置指南

    HBase 默认配置   Centos6.5下Hbase配置 官网配置文档:http://hbase.apache.org/book.html#_configuration_files 中文翻译转自: ...

  8. php中,如何将编译后的代码,反编译回去。

    编译后 <?php /*********************/ /* */ /* Version : 5.1.0 */ /* Author : RM */ /* Comment : 0712 ...

  9. python开发模块基础:collections模块&paramiko模块

    一,collections模块 在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdic ...

  10. java中抽象类跟接口的区别

    额,好吧,本来是打算转载些神马的,但是搜资料的过程中发现了一个专注与java的人,那就关注啦,以后多进他blog学习学习:http://www.cnblogs.com/chenssy/p/337670 ...