pku 1456 Supermarket 贪心优先队列的应用 or 并查集

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时,直接放入队列即可,当出现相同的我们要替换掉至最小的那个,是的我们获得利润最大。

#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[N];



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[N];



int f[N];

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;

}

  

 

 

你可能感兴趣的:(super)