zoukankan      html  css  js  c++  java
  • 斜率优化

    斜率优化

    不应该是截距优化吗 雾

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

    要注意的是,每一次枚举,斜率都是在变化的,所以要枚举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
    ",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
    ",q[head],i,slope(q[head],i),maxn);
    		if(slo>maxn+eps)
    		{
    			maxn=slo;
    		}
    	}
    	printf("%lld
    ",(long long)(maxn*1000));
    	return 0;
    }
    
    $道路千万条,点赞第一条;阅读不规范,笔者两行泪$
  • 相关阅读:
    leetcode 347. Top K Frequent Elements
    581. Shortest Unsorted Continuous Subarray
    leetcode 3. Longest Substring Without Repeating Characters
    leetcode 217. Contains Duplicate、219. Contains Duplicate II、220. Contains Duplicate、287. Find the Duplicate Number 、442. Find All Duplicates in an Array 、448. Find All Numbers Disappeared in an Array
    leetcode 461. Hamming Distance
    leetcode 19. Remove Nth Node From End of List
    leetcode 100. Same Tree、101. Symmetric Tree
    leetcode 171. Excel Sheet Column Number
    leetcode 242. Valid Anagram
    leetcode 326. Power of Three
  • 原文地址:https://www.cnblogs.com/cherrypill/p/14342700.html
Copyright © 2011-2022 走看看