poj1456 贪心+并查集
Posted dlutjwh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj1456 贪心+并查集相关的知识,希望对你有一定的参考价值。
题目链接:http://poj.org/problem?id=1456
题意:有n个物品(0 <= n <= 10000) ,每个物品有一个价格pi和一个保质期di (1 <= pi <= 10000, 1 <= di <= 10000),物品必须在保质期之前卖出。且每天只能卖出一个物品,问如何安排才能使卖出的总价格最大。
这道题贪心的思想很明显,先将物品的价格按照从大到小排序,再按照该顺序卖物品,如果存在不超过保质期的最大可用日期,则该物品能够卖出,并将这一天标记。关键在于如何找这个日期,就是在一个有序序列中查找小于等于当前日期的最大值,再将其删除,继续查找。这个可以用set来做。
#include <iostream> #include <algorithm> #include <stdio.h> #include <stack> #include <set> #include <istream> #include<queue> #include<stack> #include <cstring> #include <string> //#include <climits> using namespace std; struct products { int money, day; }; bool cmp(products a, products b) { if (a.money != b.money) return a.money > b.money; return a.day>b.day; } int main() { int n; while (scanf("%d", &n) != EOF) { set<int> s; products *p = new products[n]; int md = 0; for (int i = 0;i < n;i++) { scanf("%d%d", &p[i].money, &p[i].day); md = max(p[i].day, md); } for (int i = 1;i <= md;i++) s.insert(i); sort(p, p + n, cmp); int ans = 0; for (int i = 0;i < n && !s.empty();i++) { if (*s.begin() > p[i].day) continue; set<int>::iterator iter = s.upper_bound(p[i].day); iter--; //cout << *iter << -1 << endl; if (*iter <= p[i].day) { ans += p[i].money; s.erase(iter); } } printf("%d ", ans); delete[]p; } }
除了这种解法外,我们还可以用并查集来维护,初始化每个日期i的父亲为自己,当当前的日期i被占用后,将其父亲设为前一天的日期i-1,每次查找i的最大可用日期即查找i的祖先即可,由于使用路径压缩,所以查找的复杂度很低,比用set块
#include <iostream> #include <algorithm> #include <cstdio> using namespace std; class union_find_set { public: union_find_set(int n) { fa = new int[n]; rank = new int[n]; for (int i = 0; i < n; i++) fa[i] = i; } ~union_find_set() { delete fa,rank; }; int find(int x) { if (fa[x] == x) return x; return fa[x] = find(fa[x]); } void unite(int x, int y) { x = find(x); y = find(y); if (x == y) return; if (rank[x] < rank[y]) fa[x] = y; else { fa[y] = x; if (rank[x] == rank[y]) rank[x]++; } } bool same(int x, int y) { if (find(x) == find(y)) return 1; return 0; } int n; int *fa,*rank; }; struct products { int money, day; }; bool cmp(products a, products b) { return a.money > b.money; } int main() { int n; while (scanf("%d", &n) != EOF) { products *p = new products[n]; int md = 0; for (int i = 0;i < n;i++) { scanf("%d%d", &p[i].money,&p[i].day); md = max(p[i].day, md); } union_find_set P(md + 1); sort(p, p + n, cmp); int ans = 0; for (int i = 0;i < n;i++) { int t = P.find(p[i].day); if (t > 0) { ans += p[i].money; P.fa[t] = t - 1; } } printf("%d ", ans) ; delete p; } }
以上是关于poj1456 贪心+并查集的主要内容,如果未能解决你的问题,请参考以下文章
[POJ1456]Supermarket(贪心 + 优先队列 || 并查集)