POJ-1456 Suprmarket (并查集+贪心)

题目链接:
https://cn.vjudge.net/problem/POJ-1456

题目大意:
有N个商品,每种保质期是di,所获得收益是pi,问所能卖出的最大收益是多少
多组测试样例

题解思路:
乍一看,这不就是个贪心题吗?最优策略都在保质期的最后一天卖,选出收益最高的卖,然后 相加不就行了嘛?但是,这样是完全错误的!不加以思考的! 假如这个样例
3 1 1 5 2 3 2 答案是多少?是8!,因为从第二天看,最高收益是5,但是3收益的可以在第一天卖!

并查集数组f[i]规定:
1.f[i]=-1 代表第i天还没有卖东西,查找时返回i
2.f[i]=i-1 代表第i天已经卖过东西了,下一个第i天保质期的只能在第i-1天卖了,查找时返回Find(f[i-1])

因此,解题思路大概出来了,首先把商品的收益从大到小排,然后查找并查集数组,
如果大于0,则卖出。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int MAX=-99999;
int f[10011];//并查集数组

struct G
{//商品结构体
    int p,d;//p代表收益,d代表保质期
}goods[10011];

int Find(int x)
{//查找
    if(f[x]==-1)
        return x;
    return Find(f[x]);
}

bool cmp(G g1,G g2)
{
    return g1.p>g2.p;
}
int main()
{
    int n,t;
    while(scanf("%d",&n)!=EOF)
    {
        memset(f,-1,sizeof(f));
        int sum=0;
        memset(goods,0,sizeof(goods));
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&goods[i].p,&goods[i].d);
        }
        sort(goods,goods+n,cmp);
        for(int i=0;i<n;i++)
        {
            t=Find(goods[i].d);
            if(t>0)
            {
                sum+=goods[i].p;
                f[t]=t-1;
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}

发布了67 篇原创文章 · 获赞 42 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_26235879/article/details/98958751