COGS锯木厂选址(斜率优化)

来源:互联网 发布:域名推广 编辑:程序博客网 时间:2024/04/29 21:24

这道题,需要选两个锯木厂,标定了选的份数,以前做的题都是可以分成任意的分数

实际上,这道题n^2枚举锯木厂的位置,O( 1 ) 计算,找出最大值。


算是斜率优化,感觉不是特别好说是斜率优化dp,因为这道题,当确定了第二个锯木厂,第一个锯木厂的选择是有决策单调性,其实斜率优化就是用了处理决策单调性的问题决策选取的,这道题推式子可以推出来斜率式,能推出斜率的式子,就可以来用单调队列维护决策处理单调性了



#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;typedef long long ll;ll sum[200505],dis[200505],f[200505],ans=20000000005,s[200505];int n,q[200505],head,tail;ll getup(int j,int k){return dis[j+1]*sum[j]-dis[k+1]*sum[k];}ll getdown(int j,int k){return dis[j+1]-dis[k+1];}ll getdp(int i,int j){return -dis[j+1]*(sum[i]-sum[j])  +      s[n]-dis[i+1]*(sum[n]-sum[i]);}int main(){freopen("two.in","r",stdin);freopen("two.out","w",stdout);scanf("%d",&n);for (int i=n;i>=1;i--) scanf("%lld%lld",&sum[i],&dis[i]);for (int i=1;i<=n;i++) dis[i]+=dis[i-1],sum[i]+=sum[i-1];for (int i=1;i<=n;i++) s[i]=s[i-1]+(sum[i]-sum[i-1])*dis[i];head=tail=1;q[head]=0;f[0]=0;//?for (int i=1;i<n;i++){while (head<tail &&getup(q[head+1],q[head])<sum[i]*getdown(q[head+1],q[head])) head++;f[i]=getdp(i,q[head]);while (head<tail && getup(i,q[tail])*getdown(q[tail],q[tail-1])<getup(q[tail],q[tail-1])*getdown(i,q[tail])) tail--;q[++tail]=i;ans=min(ans,f[i]);}printf("%lld",ans);return 0;}


0 0
原创粉丝点击