POJ ~ 1456 ~ Supermarket (贪心+并查集)

题意:有N种商品,每种商品有价值和保质期。物品在保质期时间内卖出去才会有回报。问怎么卖才能得到最大回报?

4  50 2  10 1   20 2   30 1表示共有四个商品,第一个价值为50保质期为两天,第二个价值为10保质期为一天。。。

思路:贪心 + 并查集。我们肯定优先要卖贵的,所以我们需要按价值排个序。然后尽量在靠后的时间卖,因为这样可以给其他物品更多的时间进行选择。用并查集起一个标记查找作用,f[x]==-1的时候表示这一天可用,否则不可用,东西卖出去了我们就把他的父节点改为前一天。如果根节点为0的话,那么表示该物品应该放弃。

pair默认先按第一个元素从小到大排,第一个相同按第二个从小到大排。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 10005;
int n, f[MAXN];
pair<int, int> a[MAXN];
int Find(int x)
{
    if (f[x] == -1) return x;//可用的时间点
    return f[x] = Find(f[x]);
}
int main()
{
    while(~scanf("%d", &n))
    {
        memset(f, -1, sizeof(f));//初始化
        for (int i = 0; i < n; i++)
        {
            scanf("%d%d", &a[i].first, &a[i].second);
        }
        sort(a, a + n);//按价格从小到大排序
        int ans = 0;
        for (int i = n - 1; i >= 0; i--)
        {
            int day = Find(a[i].second);//找到第一个可用的时间点
            if (day > 0)//不是第0天           
            {
                f[day] = day - 1;
                ans += a[i].first;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
/*
4  50 2  10 1   20 2   30 1

7  20 1   2 1   10 3  100 2   8 2
   5 20  50 10
*/




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值