bzoj4578(斜率优化)

 

方法麻烦了,简单方法见https://oi.men.ci/sdoi2016-journey/

 

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const ll inf=1e15;
ll dp[3005][3005],sum[3005];
int n,m,i,head,tail,q[30005];

ll getup(int j,int k)
{
	return dp[i-1][j]-dp[i-1][k]+(ll)m*sum[j]*sum[j]-(ll)m*sum[k]*sum[k]+(ll)2*sum[n]*sum[j]-(ll)2*sum[n]*sum[k];
}
ll getdown(int j,int k)
{
	return (ll)2*m*(sum[j]-sum[k]);
}
ll getdp(int j,int k)
{
	return dp[i-1][k]+(ll)m*(sum[j]-sum[k])*(sum[j]-sum[k])-(ll)2*sum[n]*(sum[j]-sum[k]);
}
int main()
{
	freopen("menci_journey.in","r",stdin);
	freopen("menci_journey.out","w",stdout); 
 	scanf("%d%d",&n,&m);
 	ll x;
 	for (i=1;i<=n;i++) 
	{
		scanf("%lld",&x);
		sum[i]=sum[i-1]+x; 
	}
	for (i=0;i<=3000;i++)
		for (int j=0;j<=3000;j++) dp[i][j]=inf;
	dp[0][0]=0;
	for (i=1;i<=m;i++)
	{
		head=tail=1;
		q[1]=i-1;
		for (int j=i;j<=n;j++)
		{
			while (head<tail && getup(q[head+1],q[head])<=sum[j]*getdown(q[head+1],q[head])) head++;
			
			dp[i][j]=getdp(j,q[head]);
			
			while (head<tail && getup(j,q[tail])*getdown(q[tail],q[tail-1])<=getup(q[tail],q[tail-1])*getdown(j,q[tail])) tail--;
			q[++tail]=j;
		} 
	}
	printf("%lld",dp[m][n]+sum[n]*sum[n]);
	return 0;
}

总结

1:其实对于题目所问的问题,我们尝试处理出数学模型,将其转化为数学公式,尝试化简,再转化成斜率优化的式子

2:之所以整体斜率优化写麻烦了,实际上是对于公式没有化到最简,由此发现数学推倒的重要性!!,对于有公式出现,注意学会化简,并且积累公式化简的技巧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值