HDU3480 Division——四边形不等式或斜率优化
题目大意
思路
首先肯定要将数列排序,每部分一定是取连续的一段,于是就有了方程
$\Large f(i,j)=min(f(i-1,k-1)+(a_j-a_k)^2)$
其中$f(i,j)$表示前$j$个数分成$i$部分的最小值
解法一.四边形不等式优化
设$w(i,j)=(a_j-a_i)^2$
方程变为$f(i,j)=min(f(i-1,k-1)+w(k,j))$
很容易想到四边形不等式优化
证明w满足四边形不等式
$w(i,j)-w(i+1,j)=(a_j-a_i)^2-(a_j-a_{i+1})^2=a_i^2-a_{i+1}^2+2*a_j*(a_{i+1}-a_i)$
因为$a_{i+1}-a_i\ge 0$
所以$w(i,j)-w(i+1,j)$关于j单调不减,即$w(i,j)-w(i+1,j)\le w(i,j+1)-w(i+1,j+1)$
所以$w(i,j)+w(i+1,j+1)\le w(i,j+1)+w(i+1,j)$
以下证明具体可参考POJ1160 Post Office
证明f满足四边形不等式
设$f_k(i,j)=f(i-1,k-1)+w(k,j)$
对于$\forall i\le i^{'}\le j\le j^{'}$,设$k=s(i,j^{'}),t=s(i^{'},j)$
1.如果$k\le t$
有$f(i,j)+f(i^{'},j^{'})\le f(i-1,k-1)+w(k,j)+f(i^{'}-1,t-1)+w(t,j^{'})$
$f(i,j)+f(i^{'},j^{'})\le f(i-1,k-1)+w(k,j^{'})+f(i^{'}-1,t-1)+w(t,j)$
即$f(i,j)+f(i^{'},j^{'})\le f(i,j^{'})+f(i^{'},j)$
2.如果$k\gt t$
则只需证$f(i-1,t-1)+f(i^{'}-1,k-1)\le f(i-1,k-1)+f(i^{'}-1,t-1)$即可
设$k_1=s(i-1,k-1),k_2=s(i-2,k_1-1)……k_n=s(i-n,k_{n-1}-1)$
$t_1=s(i^{'}-1,t-1),t_2=s(i^{'}-2,t_1-1)……t_n=s(i^{'}-n,t_{n-1}-1)$
如果$k_1\le t_1$,就用1去证明
否则,递归2证明直到求证$f(1,t_n-1)+f(i_{'}-i+1,k_n-1)\le f(1,k_n-1)+f(i_{'}-i+1,t_n-1)$
化简得$w(1,t_n-1)+w(t_{n+1},k_n-1)\le w(1,k_n-1)+w(t_{n+1},t_n-1)$
因为w满足四边形不等式所以$f(i,j)+f(i^{'},j^{'})\le f(i,j^{'})+f(i^{'},j)$
证明$f(i,j)$的决策$s(i,j)$是单调的
1.设$k=s(i,j)$,对于所有$t\le k$
有$w(t,j)+w(k,j+1)\le w(t,j+1)+w(k,j)$
两边同时加上$f(i,t-1)+f(i,k-1)$得$f_t(i,j)+f_k(i,j+1)\le f_k(i,j)+f_t(i,j+1)$
因为$f_t(i,j)\ge f_k(i,j)$,所以$f_k(i,j+1)\le f_t(i,j+1)$
所以$s(i,j)\le s(i,j+1)$
2.设$k=s(i,j)$,对于所有$t\le k$
有$f(i,t-1)+f(i+1,k-1)\le f(i+1,t-1)+f(i,k-1)$
两边同时加上$w(t,j)+w(k,j)$得$f_t(i,j)+f_k(i+1,j\le f_k(i,j)+f_t(i+1,j)$
因为$f_t(i,j)\ge f_k(i,j)$,所以$f_k(i+1,j)\le f_t(i+1,j)$
所以$s(i,j)\le s(i+1,j)$
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 10005
#define maxm 5005
int f[maxm][maxn],s[maxm][maxn],a[maxn];
void work(){
int n,m;scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",a+i);
sort(a+,a+n+);
memset(f,0x3f,sizeof(f));
for(int i=;i<=n;i++)s[][i]=;
f[][]=;
for(int i=;i<=m;i++){
f[i][i]=;s[i][i]=i;s[i][n+]=n;
for(int j=n;j>i;j--){
for(int k=s[i-][j];k<=s[i][j+];k++){
if(f[i][j]>f[i-][k-]+(a[j]-a[k])*(a[j]-a[k])){
f[i][j]=f[i-][k-]+(a[j]-a[k])*(a[j]-a[k]);
s[i][j]=k;
}
}
}
}
printf("%d\n",f[m][n]);
}
int main(){
int t;scanf("%d",&t);
for(int i=;i<=t;i++)printf("Case %d: ",i),work();
return ;
}
解法二.斜率优化
若对于某个$f(i,j)$,$k$比$t$要优
那么$f(i-1,k-1)+(a_j-a_k)^2\le f(i-1,t-1)+(a_j-a_t)^2$
化简得$(f(i-1,k-1)+a_k^2-f(i-1,t-1)-a_t^2)/(2*(a_k-a_t))\le a_j$
然后就可以对每一个$i$分别用一次斜率优化$O(n)$得出$f$的值
可以用滚动数组优化空间
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 10005
#define inf 0x3fffffff
int f[][maxn],a[maxn],que[maxn],s,t,k;
int calc(int k,int i,int j){
if(a[i]==a[j])return inf;
return (f[k][i-]+a[i]*a[i]-f[k][j-]-a[j]*a[j]-)/((a[i]-a[j])<<)+;//ÏòÉÏÈ¡Õû
}
void insert(int k,int x){
while(s<t-&&calc(k,x,que[t-])<=calc(k,que[t-],que[t-]))t--;
que[t++]=x;
}
void work(){
int n,m;scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",a+i);
sort(a+,a+n+);
s=t=;que[t++]=;
for(int i=;i<=m;i++){
k=i&;f[k][i]=;
for(int j=i+;j<=n;j++){
while(s<t-&&calc(k^,que[s+],que[s])<=a[j])s++;
int x=que[s];
f[k][j]=f[k^][x-]+(a[j]-a[x])*(a[j]-a[x]);
}
s=t=;
for(int j=i+;j<=n;j++){
insert(k,j);
}
}
printf("%d\n",f[m&][n]);
}
int main(){
int t;scanf("%d",&t);
for(int i=;i<=t;i++)printf("Case %d: ",i),work();
return ;
}
HDU3480 Division——四边形不等式或斜率优化的更多相关文章
- [HDU3480] Division [四边形不等式dp]
题面: 传送门 思路: 因为集合可以无序选择,所以我们先把输入数据排个序 然后发先可以动归一波 设$dp\left[i\right]\left[j\right]$表示前j个数中分了i个集合,$w\le ...
- hdu 3480 Division(四边形不等式优化)
Problem Description Little D is really interested in the theorem of sets recently. There’s a problem ...
- [POJ1160] Post Office [四边形不等式dp]
题面: 传送门 思路: dp方程实际上很好想 设$dp\left[i\right]\left[j\right]$表示前$j$个镇子设立$i$个邮局的最小花费 然后状态转移: $dp\left[i\ri ...
- HDU-3480 Division (四边形不等式优化DP)
题目大意:将n个数分成m组,将每组的最大值与最小值的平方差加起来,求最小和. 题目分析:先对数排序.定义状态dp(i,j)表示前 j 个数分成 i 组得到的最小和,则状态转移方程为dp(i,j)=mi ...
- 【转】斜率优化DP和四边形不等式优化DP整理
(自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...
- HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)
题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程 ...
- HDU3480 Division —— 斜率优化DP
题目链接:https://vjudge.net/problem/HDU-3480 Division Time Limit: 10000/5000 MS (Java/Others) Memory ...
- BZOJ 1010 玩具装箱toy(四边形不等式优化DP)(HNOI 2008)
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...
- BZOJ1563/洛谷P1912 诗人小G 【四边形不等式优化dp】
题目链接 洛谷P1912[原题,需输出方案] BZOJ1563[无SPJ,只需输出结果] 题解 四边形不等式 什么是四边形不等式? 一个定义域在整数上的函数\(val(i,j)\),满足对\(\for ...
随机推荐
- 剑指offer——30栈的压入、弹出序列
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- 好消息:Dubbo & Spring Boot要来了
Duboo和Spring Boot都是非常优秀的框架,现在它们要结合了.为了简化Dubbo开发集成,阿里Dubbo团队将发布基于Spring Boot的版本,可快速上手Dubbo的分布式开发,并提供了 ...
- DRF的三大认证组件
目录 DRF的三大认证组件 认证组件 工作原理 实现 权限组件 工作原理 实现 频率组件 工作原理 实现 三种组件的配置 DRF的三大认证组件 认证组件 工作原理 首先,认证组件是基于BaseAuth ...
- _IRP struct
Windows XP x86 +0x000 Type : Int2B +0x002 Size : Uint2B +0x004 MdlAddress : Ptr32 _MDL +0x000 Next : ...
- Spark中的各种action算子操作(java版)
在我看来,Spark编程中的action算子的作用就像一个触发器,用来触发之前的transformation算子.transformation操作具有懒加载的特性,你定义完操作之后并不会立即加载,只有 ...
- Flutter BottomNavigationBar切换会刷新当前页面解决方
问题描述 BottomNavigationBar 是flutter 中最常用的UI组建,刚接触时发现在切换tab 的时候,会刷新当前的所有状态,每个页面都会重新刷新.于是乎,在这里先记录下解决方案. ...
- VS2017打包
转载:https://blog.csdn.net/Houheshuai/article/details/78518097 在要打包项目的解决方案 右键→添加→ 新建项目 后出现如下选择 如果没 ...
- python_django_models模块
django中models模块为各类数据库提供了统一的api,可根据不同的业务需求配置数据库. models模块开发流程: 配置数据库 详情:https://www.cnblogs.com/Vera ...
- Python_pymysql
pymysql安装:pip3 install pymysql 第一个实例:连接数据库进行用户验证 条件:数据库中已存在一个用户表,包含用户名.密码 import pymysql user = in ...
- 7python ruturn中的and与or.
def test(): a = "" return a or "hehe" #如果a为真,输出a; 否则输出右边(比如0, "", [], ...