pku 1456 Supermarket 贪心优先队列的应用 or 并查集
2013-03-04 19:05
513 查看
http://poj.org/problem?id=1456
题意:
给出n个折扣热卖的商品,给出每个产品的(pi,di)表示第i个热卖商品,卖出去可以获得利润pi,最晚期限是第di天。让你设计一个合理的出售列表,使获得的利润最多。
思路:
才开始完全理解错了题意,以为当出现最晚期限一样的时候只能买一种呢。直接排序做了。WA..后来看了discuss里面,原理理解错题意了。
首先要理解这种情况,如果有这样的数据 (2,1) (3,2),(4,2)我们要在第一天卖(3,2)第二天卖(4,2)才能得到最大的利润。那么如何求呢。我们利用优先队列来存储第几天卖那一种,那么这个优先队列的大小size就表示了我们前size天卖什么能获得最大利润,但出现后边的最后期限大于size时,直接放入队列即可,当出现相同的我们要替换掉至最小的那个,是的我们获得利润最大。
并查集的方法确实不好想。
首先我们按贪心的思路来想的话,先把所有产品按照利润从大到小排序,然后这个把这个放在截止日期那天卖出,并做好标记,如果截至日期那天已经有其他产品占用了,那么可以把这个产品卖出的时间往前推,直到找到可以卖的那一天并标记好。 那么我们就可以利用并查集,i的根find(i)就表示小于等于i的期限可以放置商品的最靠近i的天。
题意:
给出n个折扣热卖的商品,给出每个产品的(pi,di)表示第i个热卖商品,卖出去可以获得利润pi,最晚期限是第di天。让你设计一个合理的出售列表,使获得的利润最多。
思路:
才开始完全理解错了题意,以为当出现最晚期限一样的时候只能买一种呢。直接排序做了。WA..后来看了discuss里面,原理理解错题意了。
首先要理解这种情况,如果有这样的数据 (2,1) (3,2),(4,2)我们要在第一天卖(3,2)第二天卖(4,2)才能得到最大的利润。那么如何求呢。我们利用优先队列来存储第几天卖那一种,那么这个优先队列的大小size就表示了我们前size天卖什么能获得最大利润,但出现后边的最后期限大于size时,直接放入队列即可,当出现相同的我们要替换掉至最小的那个,是的我们获得利润最大。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll long long #define inf 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define N 10007 #define M 50007 using namespace std; struct node { int px,dx; }nd ; priority_queue<int,vector<int>,greater<int> >q; int n; int cmp(node a,node b) { if (a.dx != b.dx) return a.dx < b.dx; else return a.px > b.px; } int main() { // Read(); int i; while (~scanf("%d",&n)) { for (i = 0; i < n; ++i) { scanf("%d%d",&nd[i].px,&nd[i].dx); } sort(nd,nd + n,cmp); while (!q.empty()) q.pop(); for (i = 0; i < n; ++i) { // printf("%d %d\n",nd[i].dx,nd[i].px); if (nd[i].dx > q.size()) { q.push(nd[i].px); } else { int val = q.top(); if (val < nd[i].px)//将该中产品放在val所在的那一天出售 { q.pop(); q.push(nd[i].px); } } } int ans = 0; while (!q.empty()) { ans += q.top(); q.pop(); } printf("%d\n",ans); } return 0; }
并查集的方法确实不好想。
首先我们按贪心的思路来想的话,先把所有产品按照利润从大到小排序,然后这个把这个放在截止日期那天卖出,并做好标记,如果截至日期那天已经有其他产品占用了,那么可以把这个产品卖出的时间往前推,直到找到可以卖的那一天并标记好。 那么我们就可以利用并查集,i的根find(i)就表示小于等于i的期限可以放置商品的最靠近i的天。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll long long #define inf 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define N 10007 #define M 50007 using namespace std; struct node { int px,dx; }nd ; int f ; int n; int cmp(node a,node b) { return a.px > b.px; } void init(int m) { for (int i = 0; i <= m; ++i) f[i] = i; } int find(int x) { if (f[x] != x) f[x] = find(f[x]); return f[x]; } int main() { // Read(); int i; int maxT; while (~scanf("%d",&n)) { maxT = 0; for (i = 0; i < n; ++i) { scanf("%d%d",&nd[i].px,&nd[i].dx); maxT = max(maxT,nd[i].dx); } sort(nd,nd + n,cmp); init(maxT); int ans = 0; for (i = 0; i < n; ++i) { int mk = find(nd[i].dx); if (mk > 0) { ans += nd[i].px; f[mk] = mk - 1; } } printf("%d\n",ans); } return 0; }
相关文章推荐
- [POJ 1456]Supermarket[贪心][优先队列or并查集优化]
- POJ 1456 Supermarket (贪心 + 暴力 or 优先权队列 or 并查集)
- [POJ1456]Supermarket(贪心 + 优先队列 || 并查集)
- POJ 1456 supermarket(贪心加并查集)
- POJ 1456 Supermarket(贪心+并查集)
- poj 1456 - Supermarket(贪心+并查集)
- Poj 3253 Fence Repair (贪心加优先队列的应用)
- POJ---1456(Supermarket ,贪心,并查集优化,处理冲突)
- Supermarket POJ - 1456------贪心加并查集
- POJ 1456 Supermarket 区间问题并查集||贪心
- POJ 1456——Supermarket——————【贪心+并查集优化】
- POJ-1456 Supermarket(贪心,并查集优化)
- POJ-1456 Supermarket(贪心,并查集优化)
- Poj 1456 (并查集)(贪心)(优化队列)
- poj1456 Supermarket【优先队列】
- POJ 1456 Supermarket(贪心 + 并查集 )
- POJ 1456 Supermarket【贪心 + 并查集】
- poj 1456 Supermarket (贪心, 并查集)
- POJ-1456 Supermarket 贪心 并查集优化
- POJ 1456 Supermarket【贪心 + 并查集】