码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ1010】【HNOI2008】玩具装箱toy 动规_斜率优化

时间:2014-10-31 22:17:37      阅读:281      评论:0      收藏:0      [点我收藏+]

标签:bzoj1010   斜率优化   动规   

第一道斜率优化题,题解仍然不是很透彻。

我在这里可以推荐一篇博客。

http://blog.sina.com.cn/s/blog_5f5353cc0100jx41.html

写得还好,但是可能有一些地方仍说的不是很明白。


我说一下我对斜率优化的理解:

    就是发现某道动态规划的题会TLE,然后它又恰巧符合某些丧心病狂的性质时的一种优化。

    本质是有限度地捏造出一种性质,使得动规方程满足某种邪恶的单调性,从而得到大幅度的优化。

    

    而这个单调性是怎么得到的呢?

    就是我们把原转移状态搞出来,一顿转化,比如把平方拆开等,本来有两种转移j->i和k->i,我们使它原来有一个大小关系DP[j->i]<=DP[k->i],而最终转化成左边是一个有j和k的式子,右边是一个只有i的式子,这样达到高速判断两个转移哪家强的目的。

    而思想上wyf给我说了一个好理解的版本如下。

bubuko.com,布布扣

    就是它!我们要维护一个凸壳,当i要加入优先队列判断j->i的斜率和k->i的斜率,然后显然k出去了,再判断h->i,嗯,留下来了,就是这样。


    好了,说一些跟本题相关的具体东西。

    就是首先定义f[i]=sum[i]+i,这个sum[i]是前缀和。

然后有当G(j,k)/S(j,k)<=i时j比k优。

#define G(x,y) (dp[x]-dp[y]+(f[x]+c)*(f[x]+c)-(f[y]+c)*(f[y]+c))
#define S(x,y) (2*(f[x]-f[y]))


贴代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 55000
#define G(x,y) (dp[x]-dp[y]+(f[x]+c)*(f[x]+c)-(f[y]+c)*(f[y]+c))
#define S(x,y) (2*(f[x]-f[y]))
using namespace std;
long long c,sum[N],f[N],dp[N];
int n,q[N];
int main()
{
//	freopen("test.in","r",stdin);
	scanf("%d%lld",&n,&c);c++;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&sum[i]);
		sum[i]+=sum[i-1];
		f[i]=sum[i]+i;
	}
	int head=1,tail=1;
	q[1]=0;
	for(int i=1;i<=n;i++)
	{
		while(head<tail&&G(q[head+1],q[head])<=S(q[head+1],q[head])*f[i]) head++;
		dp[i]=dp[q[head]]+(f[i]-f[q[head]]-c)*(f[i]-f[q[head]]-c);
		while(head<tail&&G(i,q[tail])*S(q[tail],q[tail-1])<=G(q[tail],q[tail-1])*S(i,q[tail]))tail--;
		q[++tail]=i;
	}
	printf("%lld\n",dp[n]);
	return 0;
}



【BZOJ1010】【HNOI2008】玩具装箱toy 动规_斜率优化

标签:bzoj1010   斜率优化   动规   

原文地址:http://blog.csdn.net/vmurder/article/details/40660765

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!