题意:n个数之间放m个障碍,分隔成m+1段。对于每段两两数相乘再求和,然后把这m+1个值加起来,让这个值最小。

设:

d(i, j)表示前i个数之间放j个炸弹能得到的最小值

sum(i)为前缀和,cost(i)为前i个数两两相乘之和。

则有状态转移方程:

设0 ≤ l < k < i,且k比l更优,有不等式:

整理得到,注意不等号方向:

最后变成了斜率的形式,下面就用一个队列维护即可。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ; int n, m; int sum[maxn], cost[maxn];
int d[maxn][maxn]; int head, tail;
int Q[maxn]; int j; int inline Y(int i)
{
return d[i][j-] + sum[i] * sum[i] - cost[i];
} int inline DY(int x1, int x2) { return Y(x2) - Y(x1); } int inline DX(int x1, int x2) { return sum[x2] - sum[x1]; } int inline DP(int x1, int x2) { return d[x1][j-] + cost[x2] - cost[x1] - sum[x1]*(sum[x2]-sum[x1]); } int main()
{
while(scanf("%d%d", &n, &m) == && n)
{
for(int i = ; i <= n; i++) scanf("%d", sum + i);
for(int i = ; i <= n; i++) sum[i] += sum[i - ];
for(int i = ; i <= n; i++) cost[i] = cost[i-] + (sum[i]-sum[i-])*sum[i-]; for(int i = ; i <= n; i++) d[i][] = cost[i];
for(j = ; j <= m; j++)
{
head = tail = ;
Q[tail++] = ;
for(int i = ; i <= n; i++)
{
while(head + < tail && DY(Q[head], Q[head+]) <= sum[i] * DX(Q[head], Q[head+])) head++;
d[i][j] = DP(Q[head], i);
while(head + < tail && DY(Q[tail-], i) * DX(Q[tail-], Q[tail-]) <= DY(Q[tail-], Q[tail-]) * DX(Q[tail-], i)) tail--;
Q[tail++] = i;
}
} printf("%d\n", d[n][m]);
} return ;
}

代码君

贴一个四边形不等式优化的代码对比一下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
const int INF = 0x3f3f3f3f; int n, m;
int a[maxn], sum[maxn], cost[maxn];
int d[maxn][maxn], s[maxn][maxn]; int inline w(int k, int j)
{
return cost[j] - cost[k-] - sum[k-] * (sum[j] - sum[k-]);
} int main()
{
while(scanf("%d%d", &n, &m) == && n)
{
m++; for(int i = ; i <= n; i++) scanf("%d", a + i);
for(int i = ; i <= n; i++) sum[i] = sum[i - ] + a[i];
for(int i = ; i <= n; i++) cost[i] = cost[i-] + sum[i-] * a[i]; memset(d, , sizeof(d));
for(int i = ; i <= m; i++)
for(int j = i + ; j <= n; j++) d[i][j] = INF; for(int i = ; i <= n; i++) { d[][i] = cost[i]; s[][i] = ; }
for(int i = ; i <= m; i++)
{
s[i][n+] = n;
for(int j = n; j >= i; j--)
{
for(int k = s[i-][j]; k <= s[i][j+]; k++)
{
int tmp = d[i-][k] + w(k+, j);
if(tmp < d[i][j])
{ d[i][j] = tmp; s[i][j] = k; }
}
}
} printf("%d\n", d[m][n]);
} return ;
}

代码君

HDU 2829 斜率优化DP Lawrence的更多相关文章

  1. hdu 3669(斜率优化DP)

    Cross the Wall Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) ...

  2. HDU 4258 斜率优化dp

    Covered Walkway Time Limit: 30000/10000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  3. hdu 3045 斜率优化DP

    思路:dp[i]=dp[j]+sum[i]-sum[j]-(i-j)*num[j+1]; 然后就是比较斜率. 注意的时这里j+t<=i: #include<iostream> #in ...

  4. Print Article HDU - 3507 -斜率优化DP

    思路 : 1,用一个单调队列来维护解集. 2,假设队列中从头到尾已经有元素a b c.那么当d要入队的时候,我们维护队列的下凸性质, 即如果g[d,c]<g[c,b],那么就将c点删除.直到找到 ...

  5. HDU 3507 斜率优化dp

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  6. HDU 3507斜率优化dp

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  7. HDU 3507 斜率优化 DP Print Article

    在kuangbin巨巨博客上学的. #include <iostream> #include <cstdio> #include <cstring> #includ ...

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

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

  9. HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)

    题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程 ...

随机推荐

  1. ztr loves lucky numbers 傻逼的我来了个大模拟

    http://acm.hdu.edu.cn/showproblem.php?pid=5676 这题的正解因该是dfs的,但是有18个位,然后我一算,全排列的话,有18!个啊,那不是很大?但是有很多是相 ...

  2. Spark Mllib里如何将trainDara训练数据文件里提取第M到第N字段(图文详解)

    不多说,直接上干货! 具体,见 Hadoop+Spark大数据巨量分析与机器学习整合开发实战的第13章 使用决策树二元分类算法来预测分类StumbleUpon数据集

  3. php __autoload函数 加载类文件

    面向对象的开发时,大家肯定都会遇到这样的问题,就是加载文件,一般都是加文件的头部inclue_once,require一大堆,看着很让人烦.当然你可以自己写程序来加载.php5以后引入了__autol ...

  4. Java GUI设置图标

    ImageIcon是Icon接口的一个实现类. ImageIcon类的构造函数: ImageIcon() ImageIcon(String filename)   //本地图片文件 ImageIcon ...

  5. hihocoder1821 取卡片游戏

    思路: 博弈dp. 实现: #include <iostream> #include <algorithm> #include <cstring> using na ...

  6. MediaRecord一些使用记录

    今天学习了MediaRecord的使用,第一次使用做个记录. MediaRecord作用是声音录制,使用步骤如下: 1.新建出音频文件代码如下: 先创建出用于存储音频文件 File dir = new ...

  7. 企业CIO、CTO必读的34个经典故事

    一. 用人之道 去过庙的人都知道,一进庙门,首先是弥陀佛,笑脸迎客,而在他的北面,则是黑口黑脸的韦陀.但相传在很久以前,他们并不在同一个庙里,而是分别掌管不同的庙.弥乐佛热情快乐,所以来的人非常多,但 ...

  8. Monkey安装和使用介绍

    安装步骤1)安装sdk环境在系统环境变量中配置 ANDROID_HOMED:\sdk PATH%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;%A ...

  9. javascript基本类型和引用类型,作用域和内存问题

    基本类型(null.undefined.boolean.number.string)和引用类型(Object 对象) 1  基本类型:只能不存一个值,一种类型:从一个变量向另一个变量复制基本类型的值, ...

  10. Gym 100342I Travel Agency (Tarjan)

    题意读懂了就好做了,就是求一下点双连通分量.维护一下一颗子树的结点数,对于一个结点当u是割点的时候, 统计一下u分割的连通分量v,每得到一个连通分量的结点数cnt(v)和之前连通分量结点数sum相乘一 ...