bzoj4578(斜率优化)

来源:互联网 发布:淘宝网床上四件套 编辑:程序博客网 时间:2024/05/24 06:47

 

方法麻烦了,简单方法见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 0