poj 1180 Batch Scheduling dp斜率优化

题意:
       设dp[i]=min dp[j]+(S+sumT[i]-sumT[j])*F[i]  1<=i<=N,i<j<=N+1,sumT[i]=T[i]+T[i+1]+...+T[N],sumF[i]=F[i]+F[i+1]+...+F[N],求dp[1]。
分析:

       dp[i]=min (S+sumT[i])*sumF[i]+dp[j]-sumT[j]*F[i],由于F[i]随i减小单增,sumT[j]随i减小单增,按照i从N到1倒推dp[i]满足单调队列优化的条件dp[i]=S(i)+min{fj(i)|i<j<=N+1},其中S(i)是i的任意函数,fj是由j确定直线,使用单调队列优化到O(n)。

代码:

//poj 1180
//sep9
#include <iostream>
#include <deque>
using namespace std;
const int MAXN=10024;
int N,S,T[MAXN],F[MAXN],sumT[MAXN],sumF[MAXN],dp[MAXN];

struct Line{
	int k,b;
	Line(int k,int b):k(k),b(b){}		
};

int f(int x,Line l)
{
	return (S+sumT[x])*sumF[x]+l.b+l.k*sumF[x];
}

bool check(Line l1,Line l2,Line l3)
{
	return (l2.k-l1.k)*(l3.b-l2.b)>=(l2.b-l1.b)*(l3.k-l2.k);
}

int main()
{
	scanf("%d%d",&N,&S);
	for(int i=1;i<=N;++i)
		scanf("%d%d",&T[i],&F[i]);
	sumT[N+1]=sumF[N+1]=0;
	for(int i=N;i>=1;--i){
		sumT[i]=sumT[i+1]+T[i];
		sumF[i]=sumF[i+1]+F[i];
	}
	deque<Line> lines;
	lines.push_back(Line(0,0));
	for(int i=N;i>=1;--i){
		while(lines.size()>1&&f(i,lines[0])>=f(i,lines[1])) lines.pop_front();
		dp[i]=f(i,lines[0]);
		Line l(-sumT[i],dp[i]);
		while(lines.size()>1&&check(lines[lines.size()-2],lines[lines.size()-1],l)) lines.pop_back();
		lines.push_back(l);
	}
	printf("%d\n",dp[1]);	
	return 0;	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值