斜率优化

斜率优化

不应该是截距优化吗 雾

其实就是个线性规划问题,附上别人比我讲的好系列

要注意的是,每一次枚举,斜率都是在变化的,所以要枚举n次,而第i次枚举必须把i点加入凸包,并维护凸包的元素(表现为队列尾部出队)

而斜率优化最最最最重要的大前提是你会写dp方程

例题:玩具装箱

代码

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
int n,L;
long long a[N],sum[N],dp[N];
int q[N*2];
long long X(int i)
{
	return sum[i]+i+L+1;
}
double Y(int i)
{
	return dp[i]+X(i)*X(i);
}
double slope(int qx,int zx)
{
	return (Y(zx)-Y(qx))/(X(zx)-X(qx));
}

int main()
{
	scanf("%d %d",&n,&L);
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		sum[i]=sum[i-1]+x;
		a[i]=sum[i]+i;
	}
	dp[0]=0;
	//手动队列更好使
	int head,tail;
	head=1;
	tail=0;
	q[++tail]=dp[0];
	for(int i=1;i<=n;i++)
	{
		// head==tail 1个元素,head<tail两个元素,找第一个斜率大于直线的点
		while(head<tail&&slope(q[head],q[head+1])<=2*a[i]) head++;
		dp[i]=dp[q[head]]+(a[i]-X(q[head]))*(a[i]-X(q[head]));
		//判断i点加入凸包,凸包的改变(表现为删掉斜率大于等于的点)
		while(head<tail&&slope(q[tail-1],q[tail])>=slope(q[tail-1],i)) tail--;
		q[++tail]=i;
	}
	printf("%lld\n",dp[n]);
	return 0;
}

例题:POJ2018 Best Cow Fences

因为距离要大于等于L,所以从点L+1开始枚举,每次维护一个下凸包,因为答案单调性,暴力从对头取出点,判断i与队头的斜率更新答案,最后每次把i-L的点加入队列,维护下凸包。

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const int N=1e5+5,inf=1e9+6;
double eps=1e-6;
int n,L;
long long sum[N];
int q[N*2];
double maxn;
long long X(int i)
{
	return i;
}
double Y(int i)
{
	return sum[i];
}
double slope(int qx,int zx)
{
	return (Y(zx)-Y(qx))/(X(zx)-X(qx));
}

int main()
{
	scanf("%d %d",&n,&L);
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		sum[i]=sum[i-1]+x;
	}
	//手动队列更好使
	int head,tail;
	head=1;
	tail=0;
	q[++tail]=0;
	double maxn=-inf;
	for(int i=L;i<=n;i++)
	{
		while(head<tail&&slope(q[head],q[head+1])<=slope(q[head],i)+eps)
			head++;
		
		while(head<tail&&slope(q[tail-1],q[tail])>=slope(q[tail],i-L+1)+eps)
			tail--;
		q[++tail]=i-L+1;
		double slo=slope(q[head],i);
		// printf("???%d %d %lf %lf\n",q[head],i,slope(q[head],i),maxn);
		if(slo>maxn+eps)
		{
			maxn=slo;
		}
	}
	printf("%lld\n",(long long)(maxn*1000));
	return 0;
}
posted @ 2021-01-29 00:24  Sakura_Momoko  阅读(61)  评论(0编辑  收藏  举报