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个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...
随机推荐
- .NET系统框架
本书是一本讲解.NET技术的书籍,目标读者群也是在.NET框架(.NET Framework)下进行开发的程序员,因此我们无法回避的问题就是:什么是.NET框架?它包含了哪些内容?为开发程序提供了哪些 ...
- 微软发布WCF教程及大量示例
继前面 微软公司发布Windows Communication Foundation (WCF)和Windows CardSpace的示例程序之后,微软今天又发布了WF的教程和大量示例,对于学习WF的 ...
- 积累 ---- PHP可能会遇到的面试题
1.白盒测试和黑盒测试的区别 2.Bootstrap是什么 3.OOP是什么意思 4.git和svn的使用 5.常用的git命令 6.lamp开发环境 7.高内聚,低耦合
- centos6.x 配置bond
centos6.x 配置bond centos6.x 配置bond1 物理网卡配置2 bond0网卡配置3 查看bond0网卡状态 摘要: centos6.x下使用双网卡配置bond0, centos ...
- 【openCV学习笔记】【2】读取并播放一段视频
#include <iostream> #include <opencv/highgui.h> int main(int argc, char** argv){ cvNamed ...
- 有关implicit Intent的使用
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("geo:20.000,50.000&quo ...
- JSONObject转换Int类型--java.lang.Integer cannot be cast to java.lang.String
参数 params={"abc":0} JSONObject转换Int类型 JSONObject json = JSONObject.fromObject(params); if ...
- springboot redis简单结合
参考: https://www.cnblogs.com/ityouknow/p/5748830.htmlhttp://blog.csdn.net/i_vic/article/details/53081 ...
- 庖丁解牛-----Live555源码彻底解密(根据MediaServer讲解Rtsp的建立过程)
live555MediaServer.cpp服务端源码讲解 int main(int argc, char** argv) { // Begin by setting up our usage env ...
- 【转】 Pro Android学习笔记(九二):AsyncTask(1):AsyncTask类
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在Handler的学习系列中,学习了如何h ...