POJ1456 supermarket贪心+并查集优化

 http://poj.org/problem?id=1456

A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an integral number of time units starting from the moment the sale begins. Each product takes precisely one unit of time for being sold. A selling schedule is an ordered subset of products Sell ≤ Prod such that the selling of each product x∈Sell, according to the ordering of Sell, completes before the deadline dx or just when dx expires. The profit of the selling schedule is Profit(Sell)=Σx∈Sellpx. An optimal selling schedule is a schedule with a maximum profit. 

题目想法是

先按照价值从大到小排序,把它放在放在他的时间节点上,如果这个时间节点已经被占用,就看他的t-1...1安放

利用并查集优化的思想是初始化并查集-1,看他的父节点是否为-1,-1则返回本身节点时间,本身时间>0,就ans+,然后让它的父节点为t-1;

当我们处理第i个商品的时候,我们正常来说应该是从i的截止时间往前找,看看有没有空闲时间点来放商品i。这样查找的过程比较慢。

        这里我们用并查集来做些优化,即对于时间点t来说,如果t时间点空闲,那么fa[t]==-1。 我们用findset(t)查找可行时间点时直接就可以返回t(因为t本来就可行)。如果t时间点不空闲,那么我们令fa[t]==t-1。我们用findset(t)查找可行时间点时返回的(不一定是t-1,如果t-1被占用,返回的就不是t-1。否则返回t-1)是从t-1时间点开始递归查找的结果。
优化思想来自:
原文:https://blog.csdn.net/u013480600/article/details/21102041 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10000+5;
struct Node//商品
{
    int p;//利润
    int t;//截止时间

    bool operator<(const Node &rhs)const
    {
        return p>rhs.p;
    }
} nodes[maxn];
//findset(t)表示:t时间前的最晚一个可用时间点(可以是t)
int fa[maxn];
int findset(int x)
{
    return fa[x]==-1? x:fa[x]=findset(fa[x]);
}
int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        for(int i=0; i<n; i++)
        {
            scanf("%d%d",&nodes[i].p,&nodes[i].t);
        }
        sort(nodes,nodes+n);
//按照价值从大到小排序
        memset(fa,-1,sizeof(fa));
        int cnt=0;//最终利润
        for(int i=0; i<n; i++)
        {
            //找到i商品截止时间前的最晚一个可用时间点
            int time=findset( (nodes[i].t) );//可行;
            if(time>0)//时间可行
            {
                cnt += nodes[i].p;//加上;
                fa[time]=time-1;//下车再看nodes[i].t
                //这个时间节点是他的父节点就是time-1,不再是它本身
                //就是判断他的前一时刻;
            }
        }

        printf("%d\n",cnt);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值