poj 1180 Batch Scheduling dp斜率优化

来源:互联网 发布:疯狂java讲义在线 编辑:程序博客网 时间:2024/05/17 22:00
题意:
       设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;}