一类斜率优化的dp(特有性质:只能连续,不能交叉)
给定一个有n个数的集合,将这个集合分成m个子集,要求子集的并等于全集
求花费最小。
花费为该子集的(最大数-最小数)的平方。
我们将n个数排序,
a < b < c < d
那么不可能a,c一个集合,b,c一个集合
明显a,b一个集合,c,d一个集合更优
也就是说某一个数只能和它前面的连续几个数合起来形成一个子集。 正是因为有这个性质才能dp
dp[i][j]表示第j个数在第i个集合的最小花费
dp[i][j] = min(dp[i][j],dp[i-1][k]) 1<=k<j
dp[i-1][k1] + (a[j]-a[k1+1])^2 < dp[i-1][k2]+(a[j]-a[k2+1])^2
dp[i-1][k1]+a[k1]^2-(dp[i-1][k2]+a[k2]^2) < 2a[j]*(a[k1+1]-a[k2+1])
这样就能够用斜率优化了,由于是求最小值,所以维护一个下凸包就行了。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef int LL;
const int INF = <<;
/*
给定一个有n个数的集合,将这个集合分成m个子集,要求子集的并等于全集
求花费最小, 花费为什么每个集合的(最大值-最小值)的平方 dp[i][j]表示第j个数在第i个集合的最小花费
用滚动数组压缩空间
*/ const int N = + ;
const int M = + ;
LL a[N];
LL dp[][N];
int q[N], head, tail;
LL dw(LL a, LL b)
{
return (a - b)*(a - b);
}
LL getUp(int k1, int k2, int c)
{
return dp[c][k1] + a[k1 + ] * a[k1 + ] - (dp[c][k2] + a[k2 + ] * a[k2 + ]);
}
LL getDown(int k1, int k2)
{
return * (a[k1 + ] - a[k2 + ]);
}
int main()
{
int t, n, m;
scanf("%d", &t);
for (int k = ; k <= t; ++k)
{
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]);
sort(a + , a + n + );
n = unique(a + , a + n + ) - a - ;
if (m > n)
m = n;
int c = ;
for (int j = ; j <= n; ++j)
dp[][j] = dw(a[j], a[]);
for (int i = ; i <= m; ++i)
{
head = tail = ;
for (int j = i; j <= n; ++j)
{
while (head + < tail && getUp(j - , q[tail - ], c)*getDown(q[tail - ], q[tail - ])
<= getUp(q[tail - ], q[tail - ], c)*getDown(j - , q[tail - ]))
tail--;
q[tail++] = j - ;
while (head + < tail&&getUp(q[head + ], q[head], c) < a[j] * getDown(q[head+], q[head]))
head++;
dp[c ^ ][j] = dp[c][q[head]] + dw(a[j], a[q[head] + ]);
}
c ^= ;
}
printf("Case %d: %d\n",k, dp[c][n]);
}
return ;
}
n头牛,分成几组,每组至少有k头牛
要求费用最小,
费用是每组所有牛的moo,减去该组中最小的moo
将moo排序
那么如果是分成两组的话,那么不可能是a,c一组, b,d一组
a,b,一组比c,d一组肯定更优。
又遇到了有这种性质的题目, 连续比交叉更优,这样,才能用dp来解决,
dp[j]表示以j结尾的team的最小花费
(dp[k1]-sum[k1]+k1*moo[k1+1]) - (dp[k2]-sum[k2]+k2*moo[k2+1]) < i*(moo[k1+1]-moo[k2+1])
dp[k1]+k1*moo[k1+1] - (dp[k2]+k2*moo[k2+1]) < i * (moo[k1+1]-moo[k2+1])
所以维护递增的斜率
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef __int64 LL;
const int INF = <<;
/*
n头牛,分成几组,每组至少有k头牛
要求费用最小,
费用是每组所有牛的moo,减去该组中最小的moo
a < b < c < d
那么如果是分成两组的话,那么不可能是a,c一组, b,d一组
a,b,一组比c,d一组肯定更优。
又遇到了有这种性质的题目, 连续比交叉更优,这样,才能用dp来解决,
dp[j]表示以j结尾的team的最小花费
(dp[k1]-sum[k1]+k1*moo[k1+1]) - (dp[k2]-sum[k2]+k2*moo[k2+1]) < i*(moo[k1+1]-moo[k2+1])
dp[k1]+k1*moo[k1+1] - (dp[k2]+k2*moo[k2+1]) < i * (moo[k1+1]-moo[k2+1])
所以维护递增的斜率 */
const int N = + ;
LL moo[N], dp[N], sum[N];
int q[N], head, tail; LL getUp(int k1, int k2)
{
return dp[k1] + k1*moo[k1 + ] - sum[k1] - (dp[k2] + k2*moo[k2 + ] - sum[k2]);
}
LL getDown(int k1, int k2)
{
return moo[k1 + ] - moo[k2 + ];
}
int main()
{
int n, t;
while (scanf("%d%d", &n, &t) != EOF)
{
for (int i = ; i <= n; ++i)
{
scanf("%I64d", &moo[i]);
}
sort(moo + , moo + n + );
for (int i = ; i <= n; ++i)
sum[i] = moo[i] + sum[i - ];
for (int i = t; i <= n; ++i)
dp[i] = sum[i] - i*moo[]; head = tail = ;
q[tail++] = ;
q[tail++] = t;
int k = t + ;
for (int i = *t; i <= n; ++i)
{
while (head + < tail&&getUp(q[head + ], q[head]) < i*getDown(q[head + ], q[head]))
head++;
dp[i] = dp[q[head]] + sum[i]-sum[q[head]] - (i-q[head])*moo[q[head] + ];
while (head + < tail&&getUp(k, q[tail - ])*getDown(q[tail - ], q[tail - ]) <= getUp(q[tail - ], q[tail - ])*getDown(k, q[tail - ]))
tail--;
q[tail++] = k++;
}
printf("%I64d\n", dp[n]);
}
return ;
}
一类斜率优化的dp(特有性质:只能连续,不能交叉)的更多相关文章
- 队列优化和斜率优化的dp
可以用队列优化或斜率优化的dp这一类的问题为 1D/1D一类问题 即状态数是O(n),决策数也是O(n) 单调队列优化 我们来看这样一个问题:一个含有n项的数列(n<=2000000),求出每一 ...
- [NOI2014]购票 --- 斜率优化 + 树形DP + 数据结构
[NOI2014]购票 题目描述 今年夏天,NOI在SZ市迎来了她30周岁的生日. 来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每 ...
- Luogu P5468 [NOI2019]回家路线 (斜率优化、DP)
题目链接: (luogu) https://www.luogu.org/problemnew/show/P5468 题解: 爆long long毁一生 我太菜了,这题这么简单考场上居然没想到正解-- ...
- [bzoj 2726] 任务安排 (斜率优化 线性dp)
3月14日第三题!!!(虽然是15号发的qwq) Description 机器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3-N.这N个任务被分成若干批 ...
- 斜率优化DP讲解
对于斜率优化的DP转移方程,一般以w[i]=max(w[j]+(sum[i]-sum[j])*v)的1D1D形式为主,直观看来就是前j个为若干个阶段,第j+1到第i个为一个阶段,每个阶段有自己的代价或 ...
- 【BZOJ-1597】土地购买 DP + 斜率优化
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2931 Solved: 1091[Submit] ...
- [HNOI2008]玩具装箱TOY --- DP + 斜率优化 / 决策单调性
[HNOI2008]玩具装箱TOY 题目描述: P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京. 他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器 ...
- DP玄学优化——斜率优化
--以此博客来悼念我在\(QBXT\)懵逼的时光 \(rqy\; tql\) (日常%\(rqy\)) 概念及用途 斜率优化是\(DP\)的一种较为常用的优化(据说在高中课本里稍有提及),它可以用于优 ...
- DP斜率优化学习笔记
斜率优化 首先,可以进行斜率优化的DP方程式一般式为$dp[i]=\max_{j=1}^{i-1}/\min_{j=1}^{i-1}\{a(i)*x(j)+b(i)*y(j)\}$ 其中$a(j)$和 ...
随机推荐
- c++/c/java 资源共享群
Hi,我邀请你加入360云盘文件共享群:c++&c&java, 打开邀请链接:http://qun.yunpan.360.cn/10005202 , 输入邀请码:1357
- Web.xml配置具体解释之context-param
转自:http://blog.csdn.net/liaoxiaohua1981/article/details/6759206 格式定义: [html] view plaincopy <cont ...
- ios html5 设定PhoneGap开发环境
怎么样IOS平台搭建PhoneGap开发环境(PhoneGap2.5) (2013-03-13 14:44:51) 标签: c=blog&q=it&by=tag" targe ...
- Photoshop图象切片保存为网页HTML(DIV+CSS布局)的方法
首先,制作图象切片(以一张图片为例子) 一.选择“切片”工具,在图像上拖动以分割图像(例如:一张图像切割2次就形成3个切片)切片后如下图 二.设置切片选项(如大小.目标链接.图片说明等等):选择“切片 ...
- ASP.Net状态管理读书笔记--思维导图
课前提问几个问题 使用Session 配置 model aspnet_regsql.exe 常见问答 问:为什么Session在有些机器上偶尔会丢失?答:可能和机器的环境有关系,比如:防火墙或者杀毒软 ...
- IT痴汉的工作现状16-职业发展
回首多年来的工作经历.发现自己的职业发展真是太平庸只是了.就像我的名字张伟,平淡无奇.而我,还是几年前刚入职模样的我,仍然像个涉世未深的矛头小子,相信技术能够改变世界.真是一入IT深似海,为伊消得人憔 ...
- poj 1611 The Suspects(并查集)
The Suspects Time Limit: 1000MS Memory Limit: 20000K Total Submissions: 21598 Accepted: 10461 De ...
- 数字证书, 数字签名, SSL(TLS) , SASL .
因为项目中要用到TLS + SASL 来做安全认证层. 所以看了一些网上的资料, 这里做一个总结. 1. 首先推荐几个文章: 数字证书: http://www.cnblogs.com/hyddd/ar ...
- 如何为linux释放内存和缓存
如何为linux释放内存和缓存_华陌飞尘_新浪博客 如何为linux释放内存和缓存 (2011-10-20 10:49:01) 标签: linux swap me ...
- 无法引入import com.sun.management.OperatingSystemMXBean
现象:在JDK的安装包的jre\lib\rt.jar包里确实有这个类com.sun.management.OperatingSystemMXBean,但是就是不能import com.sun.man ...