斜率化dp
来源:互联网 发布:天谕玉虚捏脸数据分享 编辑:程序博客网 时间:2024/05/24 04:19
给你一个序列,至多或分成m段,每段有花费和限制,问符合情况的最小花费是多少。有限制的情况就是一个二维dp了,现在我们只考虑下没有限制的时候。
dp[i]表示到第i个数的时候最小的花费。则dp[i]=dp[j]+(sum[i]-sum[j])^2,(这里以求每段区间平方和最小为例)。
我们用单调队列进行维护,首先是这个元素可不可以进入队列,进入之前,队尾的元素有哪些可以被弹出来。求解时,要判断队首两个元素间谁是更好的一个解。
j比k优,则dp[j]+sum[j]^2-dp[k]+sum[k]^2<=sum[i]*2*(sum[j]-sum[k]).可转化成g[j,k]<sum[i].而当新来一个元素i时,如果g[i,j]<g[j,j-1],则当前的j可以被弹出去,继续进行判断,直到大于。而每次求dp[i]时,判断下队首两个元素谁更优些。
//n个数字,划分成几个段,每个段为这几个数的和的平方+常数m。现在求如何划分使得总和最小
#include<iostream>
#include<cstdio>
#include<queue>
const int maxn=5*1e5+10;
int dp[maxn],sum[maxn];
int q[maxn];//队列
int n,m;
using namespace std;
int getdp(int i,int j)
{
return dp[j]+sum[i]*sum[i]+sum[j]*sum[j]-2*sum[i]*sum[j]+m;
}
int getup(int j,int k)
{
return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k];
}
int getdown(int j,int k)
{
return 2*(sum[j]-sum[k]);
}
int main()
{
int n,m;
int head,tail;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
scanf("%d",&sum[i]);
sum[0]=dp[0];
for(int i=1;i<=n;i++)
sum[i]+=sum[i-1];//sum[i]存储的是前i个数据的和
head=tail=0;
q[tail++]=0;
for(int i=1;i<=n;i++)
{
while(head+1<tail&&getup(q[head+1],q[head])<=sum[i]*getdown(q[head+1],q[head]))//求解时,如果前面的比后面的更优,就取得
head++;
dp[i]=getdp(i,q[head]);
while(head+1<tail&&getup(i,q[tail-1])*getdown(q[tail-1],q[tail-2])<=getup(q[tail-1],q[tail-2])*getdown(i,q[tail-1]))//如果g[i,j]<g[j,k]时,就将当前队尾元素弹出去
tail--;
q[tail++]=i;
}
printf("%d\n",dp[n]);
}
return 0;
}
待续,关于二维dp
- 斜率化dp
- 斜率dp
- DP(斜率优化)
- 【斜率优化DP】Batch_Scheduling
- dp优化--斜率
- 斜率优化DP
- 斜率优化DP
- hdu3507斜率优化dp
- DP斜率优化总结
- hdu3480 斜率优化dp
- hdu3045之斜率DP
- hdu3507 斜率优化dp
- 斜率优化DP
- 斜率dp模板
- 斜率优化DP 【pascal】
- 斜率优化DP
- dp 斜率优化
- 斜率优化 DP
- shell常用命令
- Eclipse中常见问题及解决方案
- jsonp结合百度接口-实现搜索功能
- 闭包详解
- 凸优化-对偶问题
- 斜率化dp
- STN-LCD屏学习
- 通过观察者在此activity中更新其他activity中的UI
- 入门Webpack,看这篇就够了
- hadoop 基本操作命令
- 【深度学习】Ubuntu 常用软件安装:Matlab + XX-net + ... + TeamViewer + Tensorflow + Caffe
- 关于Android沉浸式状态栏的设置以及相关问题
- H5开发:UI问题汇总
- 2017 江苏省赛(湘潭市ccpc)H题