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

[POJ1180]Batch Scheduling 斜率优化DP

时间:2015-04-09 08:44:23      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:

Description

 

  There is a sequence of N jobs to be processed on one machine. The jobs are numbered from 1 to N, so that the sequence is 1,2,..., N. The sequence of jobs must be partitioned into one or more batches, where each batch consists of consecutive jobs in the sequence. The processing starts at time 0. The batches are handled one by one starting from the first batch as follows. If a batch b contains jobs with smaller numbers than batch c, then batch b is handled before batch c. The jobs in a batch are processed successively on the machine. Immediately after all the jobs in a batch are processed, the machine outputs the results of all the jobs in that batch. The output time of a job j is the time when the batch containing j finishes. 

  A setup time S is needed to set up the machine for each batch. For each job i, we know its cost factor Fi and the time Ti required to process it. If a batch contains the jobs x, x+1,... , x+k, and starts at time t, then the output time of every job in that batch is t + S + (Tx + Tx+1 + ... + Tx+k). Note that the machine outputs the results of all jobs in a batch at the same time. If the output time of job i is Oi, its cost is Oi * Fi. For example, assume that there are 5 jobs, the setup time S = 1, (T1, T2, T3, T4, T5) = (1, 3, 4, 2, 1), and (F1, F2, F3, F4, F5) = (3, 2, 3, 3, 4). If the jobs are partitioned into three batches {1, 2}, {3}, {4, 5}, then the output times (O1, O2, O3, O4, O5) = (5, 5, 10, 14, 14) and the costs of the jobs are (15, 10, 30, 42, 56), respectively. The total cost for a partitioning is the sum of the costs of all jobs. The total cost for the example partitioning above is 153. 

  You are to write a program which, given the batch setup time and a sequence of jobs with their processing times and cost factors, computes the minimum possible total cost. 
 
 
  看这道题的形式和数据范围,斜率优化其实已经很明显。
  但是当我们想要写转移的时候却遇到了麻烦...
  计算当前花费的时候需要用到上一阶段的所用时间
  且这个所用时间与其花费并没有什么关系
  要保证正确性只能写一个看起来非常不爽的二维DP
  我们会想,之前加工的时间会影响到当前从而不好处理,那我们能不能让现在的时间去影响之前的结果呢?
  答案是肯定的,我们可以将状态反过来定义。用f[i]表示i..n的费用和。
    f[i]=f[j]+(s*t[i]-t[j])*F[i]
  t[i]表示i..n零件加工时间和,F[i]表示i..n的零件权值和。
  这样一来,问题就明朗许多了。可以用普通的斜率优化进行。
  设i<j<k 设此时取j比k好,则列出不等式
    f[j]+(t[i]-t[j])*F[i]<f[k]+(t[i]-t[k])*F[i]
  化简得
    F[i]>(f[j]-f[k])/(t[j]-t[k]) 
  这是我们熟悉的斜率表达式。设它为g[j,k]
  维护一个下凸的单调序列。
  求解当前答案的时候,我们可以通过g来得知哪些点取来更优
  很容易发现当维护好序列单调性时,(g[j,k]<F[i])是满足00000011111的
  也就是遇到的第一个1的位置时的j就是我们所要求的状态。
  求解直接按照推出的方程式转移即可。
  接着我们要把当前点加入,同时维护单调性。
  
  代码十分短感觉很优美>_<
 

 
program poj1180;
const maxn=10010;
var i,head,tail,n,s:longint;
    opt,dp,f,t:array[-1..maxn]of int64;

function g(x,y:longint):extended;
begin
    exit((dp[x]-dp[y])/(t[x]-t[y]));
end;

begin
    readln(n);
    readln(s);
    for i:=1 to n do readln(t[i],f[i]);
    for i:=n-1 downto 1 do
    begin
        inc(t[i],t[i+1]);
        inc(f[i],f[i+1]);
    end;
    t[n+1]:=0;f[n+1]:=0;
    head:=1;tail:=1;opt[1]:=n+1;dp[n+1]:=0;
    for i:=n downto 1 do
    begin
        while (head<tail)and(g(opt[head+1],opt[head])<f[i]) do inc(head);
        dp[i]:=dp[opt[head]]+(s+t[i]-t[opt[head]])*f[i];
        while (head<tail)and(g(opt[tail],opt[tail-1])>g(i,opt[tail])) do dec(tail);
                inc(tail);opt[tail]:=i;
    end;
    writeln(dp[1]);
end.

 

[POJ1180]Batch Scheduling 斜率优化DP

标签:

原文地址:http://www.cnblogs.com/mjy0724/p/4408642.html

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