斜率优化简单的模板(HDU3507)

Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate this degree.
One day Zero want to print an article which has N words, and each word i has a cost Ci to be printed. Also, Zero know that print k words in one line will cost


M is a const number.
Now Zero want to know the minimum cost in order to arrange the article perfectly

先说一下斜率优化,就是对一个dp方程的优化,降低复杂度,排除一些不需要的因素,具体我也不清楚。

先定义g(b,a)为状态,若g(b,a)<sum(b)则b比a好若g(b,a)>g(c,b)则b不用考虑。

由于可能出现重复,所以要用=号。

注意队列的=和<的使用我也不明白为什么。(问了wxs大爷,凸包斜率的比较一定要建立在3个点,2个点不可以比较orz)

先理解到这里吧,以后整理的时候加上。

#include<iostream>
#include<cstring>
#include <cstdio>
#include<cstdlib>
#include<algorithm>
#define maxn 2000000
using namespace std;
int dp[maxn],q[maxn],sum[maxn];
int n,m;

int Mathh(int i,int j)
{
	return dp[i]+sum[i]*sum[i]-dp[j]-sum[j]*sum[j];
}
int Matht(int i,int j)
{
	return 2*(sum[i]-sum[j]);
}
int DP(int i,int j)
{
	return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
}

int main()
{
	while(cin>>n>>m)
	{
		memset(dp,0,sizeof(dp));
		memset(q,0,sizeof(q));
		memset(sum,0,sizeof(sum));
		for(int i=1;i<=n;i++)
		{
			int x;cin>>x;
			sum[i]=sum[i-1]+x;
		}
		int head=0,tail=0;
		for(int i=1;i<=n;i++)
		{
			while(head<tail&&Mathh(q[head+1],q[head])<=sum[i]*Matht(q[head+1],q[head])) head++;
			dp[i]=DP(i,q[head]);
			while(head<tail&&Mathh(i,q[tail])*Matht(q[tail],q[tail-1])<=Mathh(q[tail],q[tail-1])*Matht(i,q[tail]))
				tail--;
			q[++tail]=i;
			
		}
		cout<<dp[n]<<endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值