POJ 1180 Slope Optimized DP (Monotonic Queue)

Batch Scheduling
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 4347   Accepted: 1992

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 + (T x  + T x+1  + ... + T x+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. 

Input

Your program reads from standard input. The first line contains the number of jobs N, 1 <= N <= 10000. The second line contains the batch setup time S which is an integer, 0 <= S <= 50. The following N lines contain information about the jobs 1, 2,..., N in that order as follows. First on each of these lines is an integer Ti, 1 <= Ti <= 100, the processing time of the job. Following that, there is an integer Fi, 1 <= Fi <= 100, the cost factor of the job.

Output

Your program writes to standard output. The output contains one line, which contains one integer: the minimum possible total cost.

Sample Input

5
1
1 3
3 2
4 3
2 3
1 4

Sample Output

153

Source

The meaning of the question: N tasks are arranged in a sequence on a machine to be completed one after another, and these N tasks are divided into several batches of adjacent tasks. The time it takes for the i-th task to complete alone is Ti. Before each batch of tasks starts, the machine needs to start the time S, and the time required to complete the batch of tasks is the sum of the time required for each task (the same batch of tasks will be completed at the same time). The cost of each task is the time it takes to multiply by a cost factor Fi. Please identify a grouping plan that minimizes the total cost. (1 <= N <= 10000)
Ideas: sumT[i] represents the total time required for tasks from i to n, sumF[i] represents the sum of cost coefficients from i to n, and dp[i] represents the optimal solution for the task arrangement from i to n :

      dp[i]=min(dp[j]+(sunT[i]-sumT[j]+s)*sumF[i]) (1<=i<=n+1;i<j<=n+1)

We consider that when calculating dp[i], for i < j < k, if the condition that decision k is guaranteed to be greater than decision j is: dp[j] + (S + sumT[i] - sumT[j]) * sumF[i] < dp[k] + (S + sumT[i] -sumT[k]) * sumF[i]

By shifting items, it can be simplified to: (dp[j] - dp[k]) / (sumT[j] - sumT[k]) < sumF[i]

It can be seen that when we calculate dp[i], if (dp[j] - dp[k]) / (sumT[j] - sumT[k]) >=sumF[i], we can discard j (decision K is better than decision j);

Therefore, we can use a monotonic queue. When the element i needs to be paired, (i<j<k), how do we maintain it? Let’s set the function Q(j,k)=(dp[j] - dp[k]) / (sumT[j] - sumT[k]);

Because i needs to be paired, what we need to discuss is whether we need to keep the decision j, (we will discuss the conditions for J to be discarded below);

If j needs to be discarded, that is, for decision i, j, i is better than j; for decision j, k, k is better than j; so we have Q(i,j)<sumF[i],sumF[i]<=Q (j,k); That is, Qi,j)<Q(j,k);

To sum up: you can consider maintaining a queue with a slope to optimize the entire DP process:

(1) Assuming that i (the element to be enqueued soon) < j < k is the element at the end of the queue, then we have to consider whether Q(i,j) is greater than Q(j,k), if Q(i,j) ) < Q(j,k), then it is certain that j will not be a decision point, and j can be removed from the queue and pushed forward in turn until a queue with less than 2 elements is found or Q(i,j)> = Q(j,k) to stop.

(2) Assuming k>j (k is the head element) is the element that is the head of the queue in turn, if g(j,k) < sumF[i], then decision point j is definitely better than decision point k for i , and since sumF[i] increases as i decreases,

So when Q(j,k) < sumF[i], there must be Q(j,k) < sumF[i-1], so the current decision point k is not only when considering dp[i] The best decision point, and it must not be the best decision point in the following DP, so we can delete k from the head of the queue, and so on in turn, until the queue element is less than 2 or Q(j,k )>= sumF[i].

Code:

 1 #include<sstream>
 2 #include<iomanip>
 3 #include"cstdio"
 4 #include"map"
 5 #include"set"
 6 #include"cmath"
 7 #include"queue"
 8 #include"vector"
 9 #include"string"
10 #include"cstring"
11 #include"time.h"
12 #include"iostream"
13 #include"stdlib.h"
14 #include"algorithm"
15 #define db double
16 #define ll long long
17 #define vec vectr<ll>
18 #define mt  vectr<vec>
19 #define ci(x) scanf("%d",&x)
20 #define cd(x) scanf("%lf",&x)
21 #define cl(x) scanf("%lld",&x)
22 #define pi(x) printf("%d\n",x)
23 #define pd(x) printf("%f\n",x)
24 #define pl(x) printf("%lld\n",x)
25 //#define rep(i, x, y) for(int i=x;i<=y;i++)
26 #define rep(i, n) for(int i=0;i<n;i++)
27 const int N   = 1e4+ 5;
28 const int mod = 1e9 + 7;
29 const int MOD = mod - 1;
30 const int inf = 0x3f3f3f3f;
31 const db  PI  = acos(-1.0);
32 const db  eps = 1e-10;
33 using namespace std;
34 ll dp[N];
35 int st[N],sf[N],deq[N];
36 int t[N],f[N];
37 int n,s;
38 db cal(int x,int y){
39     return db(dp[x]-dp[y])/db(st[x]-st[y]);
40 }
41 int main()
42 {
43     ci(n),ci(s);
44     for(int i=1;i<=n;i++) ci(t[i]),ci(f[i]);
45     for(int i=n;i;i--) st[i]=st[i+1]+t[i],sf[i]=sf[i+1]+f[i];
46     int l=1,r=0;
47     dp[n]=(s+st[n])*sf[n];
48     deq[++r]=n;
49     for(int i=n-1;i;i--)
50     {
51         while(r-l>=1 && cal(deq[l],deq[l+1])<sf[i]) l++;
52         int tt=s+st[i];
53         tt*=sf[i];
54         dp[i]=tt;
55         int j=deq[l];
56         tt=s+st[i]-st[j];
57         tt*=sf[i];
58         dp[i]=min(dp[i],dp[j]+tt);
59         while(r-l>=1 && cal(deq[r-1],deq[r])>cal(deq[r],i)) r--;
60         deq[++r]=i;
61     }
62     pl(dp[1]);
63     return 0;
64 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324933512&siteId=291194637