poj 1456 Supermarket - 并查集 - 贪心

题目传送门

  传送点I

  传送点II

题目大意

  有$n$个商品可以销售。每个商品销售会获得一个利润,但也有一个时间限制。每个商品需要1天的时间销售,一天也只能销售一件商品。问最大获利。

  考虑将出售每个物品尽量外后安排。这样当一个商品不能安排的时候看能不能替换掉它能够出售的时间中盈利最小的商品。

  因此可以将物品排序,这样只用考虑能否让每个物品出售。

  为了找到第一个空闲时间,又因为已经安排的时间不会改变,所以用并查集将已经安排了出售的时间段缩起来。

Code

 1 /**
 2  * poj
 3  * Problem#1456 
 4  * Accepted
 5  * Time: 47ms
 6  * Memory: 768k
 7  */
 8 #include <algorithm>
 9 #include <iostream>
10 #include <cstdlib>
11 #include <cstring>
12 #include <cstdio>
13 #include <queue>
14 using namespace std;
15 typedef bool boolean;
16 
17 typedef class Product {
18     public:
19         int profit;
20         int deadline;
21 
22         Product() {    }
23 
24         boolean operator < (Product b) const {
25             return profit > b.profit;
26         }
27 }Product;
28 
29 const int N = 1e4 + 5;
30 
31 int n, res;
32 int pre[N];
33 Product *ps;
34 boolean vis[N]; 
35 
36 inline boolean init() {
37     if (scanf("%d", &n) == EOF)
38         return false;
39     res = 0;
40     ps = new Product[(n + 1)];
41     for (int i = 1; i <= n; i++)
42         scanf("%d%d", &ps[i].profit, &ps[i].deadline);
43     return true;
44 }
45 
46 int findPre(int p) {
47     if (!p)    return 0;
48     if (!vis[p]) {
49         vis[p] = true;
50         return p;
51     }
52     return pre[p] = findPre(pre[p]); 
53 }
54 
55 inline void solve() {
56     sort(ps + 1, ps + n + 1);
57     memset(vis, false, sizeof(vis));
58     for (int i = 1; i <= 10000; i++)
59         pre[i] = i - 1;
60     for (int i = 1; i <= n; i++) {
61         int p = findPre(ps[i].deadline);
62         if (p)
63             res += ps[i].profit;
64     }
65     printf("%d\n", res);
66     delete[] ps;
67 }
68 
69 int main() {
70     while (init())
71         solve();
72     return 0;
73 }
posted @ 2018-08-04 23:10 阿波罗2003 阅读(...) 评论(...) 编辑 收藏