一类斜率优化的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)$和 ...
随机推荐
- android原生browser分析(一)--Application
类Browser.java是整个应用的Application.其代码例如以下: public class Browser extends Application { @Override public ...
- android面试题2
一.属于GLSurFaceView特性的是: 1.管理一个surface,这个surface就是一块特俗的内存.能直接排版到Android的视图view上. 2.管理一个EGL display,它能让 ...
- 推荐一款功能强大的js 在线编辑器
http://jszi.cn/public/oherub/11/edit
- 所有CN_消息的说明
Notification Message Corresponding WindowsConstant Message Description cn_CharToItem wm_CharToItem T ...
- linux下的块设备驱动(二)
上一章主要讲了请求队列的一系列问题.下面主要说一下请求函数.首先来说一下硬盘类块设备的请求函数. 请求函数可以在没有完成请求队列的中的所有请求的情况下就返回,也可以在一个请求都不完成的情况下就返回. ...
- 【MFC两种视频图像採集方法】DirectShow与Opencv
效果图: DirectShow採集核心代码: 创建线程调用该函数,採集图像通过x264解码封装rtmp协议包.推送至FMSserver,可实现视频直播 UINT __stdcall StartVide ...
- ASI简单实现网络编程
使用iOS SDK中的HTTP网络请求API,相当的复杂,调用比較麻烦.ASIHTTPRequest 对CFNetwork API进行了封装.而且使用起来非常easy的一套API,在非常多比較老旧的项 ...
- ie浏览器提交参数和其它浏览器的区别
场景描述: 用户注册模块(ajax提交方式,post方法),在url后追加了一个参数,如:url+‘btnvalue=中文参数’,如此在非ie浏览器注册时,功能完好,但在ie下注册不成功.调式后发现在 ...
- 算法起步之Dijkstra算法
原文:算法起步之Dijkstra算法 友情提示:转载请注明出处[作者 idlear 博客:http://blog.csdn.net/idlear/article/details/19687579 ...
- Pyocr 0.2 发布,Python 的 OCR 库 - 开源中国社区
Pyocr 0.2 发布,Python 的 OCR 库 - 开源中国社区 Pyocr 0.2 发布,Python 的 OCR 库