UVa1153 Keep the Customer Satisfied

Simon and Garfunkel Corporation (SG Corp.) is a large steel-making company with thousand of customers. Keeping the customer satisfied is one of the major objective of Paul and Art, the managers.

Customers issue orders that are characterized by two integer values q , the amount of steel required (in tons) and d , the due date (a calender date converted in seconds). The due date has to be met if SG Corp. accepts the order. Stated another way, when an order is accepted, the corresponding amount of steel has to be produced before its due date. Of course, the factory can process no more than one order at a time.

Although the manufacturing process is rather complex, it can be seen as a single production line with a constant throughput. In the following, we assume that producing q tons of steel takes exactly q seconds (i.e., throughput is 1). The factory runs on a monthly production plan. Before the beginning of the month, all customers' orders are collected and Paul and Art determine which of them are going to be accepted and which ones are to be rejected in the next production period. A production schedule is then designed. To keep customers satisfied, Paul and Art want to minimize the total number of orders that are rejected. In the following, we assume that the beginning of the next production plan (i.e., the first day of the next month) corresponds to date 0.

Hogdson and Moore have been appointed as Chief Scientific Officers and you are requested to help them to compute an optimal solution and to build a schedule of all accepted orders (starting time and completion time).

 

 


Small Example

 


Consider the following data set made of 6 orders J1,..., J6 . For a given order, Jj , qj denotes the amount of steel required and dj is the associated due date.

 

Order qj dj
J1 6 8
J2 4 9
J3 7 15
J4 8 20
J5 3 21
J6 5 22

You can check by hand that all orders cannot be accepted and it's very unlikely you could find a solution with less than two rejected orders. Here is an optimal solution: Reject J1 and J4 , accept all other orders and process them as follows.

 

Accepted Order Starting Time Completion Time
J2 0 4
J3 4 11
J5 11 14
J6 14 19

Note that the production line is never idle.

 

Input 

The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

 

 


Data Each test case is described by one input file that contains all the relevant data: The first line contains the number n of orders (n <can be as large as 800000 for some test cases). It is followed by n lines. Each of which describes an order made of two integer values: the amount of steel (in tons) required for the order (lower than 1000) and its due date (in seconds; lower than x 106 ).

 

Output 

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

 

 


You are required to compute an optimal solution and your program has to write the number of orders that are accepted.

 

Sample Input 

 

1

6
7 15
8 20
6 8
4 9
3 21
5 22

 

Sample Output 

 4

Some Hints from Hogdson and Moore

  • Hogdson and Moore claim that it is optimal to sequence accepted orders in non-decreasing order of due dates.
  • They also claim that there is an optimal solution such that for any two orders Ju and Jv with qu > qv and du < dv, if Ju is accepted then Jv is also accepted.
  • Finally, Hogdson and Moore advise you to ``Keep the Customer Satisfied"

Keep the Customer Satisfied

 题目大意:钢铁公司有N个客户的订单,每个订单有一个产量q(生产时间刚好也等于q)和订单完成截止时间。公司要求完成尽量多的订单。

题解:贪心问题,题目的Hints已经说的很明白了。先按订单的截止时间排序,然后挑选能够在截止时间前完成的订单,如果当前订单无法在截止时间前完成,则在已经选择的订单中找到一个生产时间大于当前订单的生产时间的订单(已选择的订单数大于0),假设为p,用当前订单替换p订单,因为当前订单的生成时间更短,且截至时间更久,选择当前这个订单得到的结果显然不会比p订单糟糕。PS:刚开始做得时候在寻找已经选择的订单中的最大生产时间的订单是直接用循环进行查找的,果断TLE了。。。因为这样的话时间时间复杂度为O(n^2)n=800000。。。无限超时啊。。。优先队列(堆)有个性质,元素之间是保持有序的,分大根堆和小跟堆,对于大根堆,堆首元素就是堆中的最大值,因此查找堆首元素只需O(1)的时间,维护一个已经建立好的堆,只需要logn的时间。对于此题,我们用优先队列刚好可以完美的解决,时间复杂度为O(nlogn)。不过如果用C语言的话,只能自己写堆。。。。早忘记是怎么样子的了。。。。不过C++的STL中刚好有优先队列,果断偷懒用了下,嘿嘿。不过以后还是得自己知道怎么写堆才行,不能太依赖STL。不过在熟练的基础上偷懒用用STL还是可以滴,特别是在比赛的时候O(∩_∩)O。准备四月份开始学习下C++,重点学习STL。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 #define MAXN 800005
 7 typedef struct
 8 {
 9     int q;
10     int d;
11 } NODE;
12 NODE a[MAXN];
13 int n;
14 bool cmp(NODE a,NODE b)
15 {
16     return a.d<b.d;
17 }
18 int main(void)
19 {
20     int i,ans;
21     int T;
22     scanf("%d",&T);
23     while(T--)
24     {
25         scanf("%d",&n);
26         for(i=0; i<n; i++)
27             scanf("%d%d",&a[i].q,&a[i].d);
28         sort(a,a+n,cmp);
29         priority_queue<int>q;
30         while(!q.empty()) q.pop();
31         ans=0;
32         for(i=0;i<n;i++)
33         if(a[i].q+ans>a[i].d)
34         {
35         if(!q.empty())
36         {
37              if((q.top()>a[i].q)&&((ans+a[i].q-q.top())<=a[i].d))
38              {
39                  ans-=q.top();
40                  q.pop();
41                  q.push(a[i].q);
42                  ans+=a[i].q;
43               }
44         }
45         }
46         else
47         {
48             q.push(a[i].q);
49             ans+=a[i].q;
50         }
51         printf("%d\n",q.size());
52         if(T) printf("\n");
53     }
54     return 0;
55 }

 

原文地址:https://www.cnblogs.com/zjbztianya/p/2987985.html