题目链接:1456 -- Supermarket
原题意比较难理解,下面我给出一个简化版的理解方式:超市里有n个商品。第i个商品必须在保质期(第di天及之前)卖掉,若卖掉可让超市获得pi的利润,但是每天只能卖一件商品,现在你要让超市获得最大的利润,问最大的利润是多少,多组数据
分析:贪心的思想,就是我们先把商品按照利润进行排序,同样是花费一天,能把利润高的商品卖掉就先把利润高的商品卖掉,但是在当前条件允许的情况下能多晚卖就多晚卖(为了给一些利润低但是保质期短的商品多提供一些时间),很明显这是一个正确的贪心策略,但是我们如何实现呢,我们不可能对于任意一件商品都从其保质期截至日期开始往前寻找,若找到一天可用来卖当前商品就卖,否则就不卖,这样复杂度有点高,我们可以用并查集来实现这个过程规定fu[i]为从i开始往前找可以找到的空余时间,初始设置为i,每次使用完这个空余时间后我们令fu[fu[i]]=fu[i]-1,(若fu[i]<1则该商品无法卖出)由于并查集查找过程中有路径压缩,所以会大大减少我们的查询时间
下面是代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=10003;
int fu[N];
struct node{
int d,p;
}p[N];
bool cmp(node a,node b)
{
return a.p>b.p;
}
int find(int x)
{
if(x==fu[x]) return x;
return fu[x]=find(fu[x]);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=10000;i++)
fu[i]=i;
for(int i=1;i<=n;i++)
scanf("%d%d",&p[i].p,&p[i].d);
sort(p+1,p+n+1,cmp);
long long ans=0;
for(int i=1;i<=n;i++)
{
int f=find(p[i].d);
if(f>=1)
{
fu[f]=f-1;
ans+=p[i].p;
}
}
printf("%lld\n",ans);
}
return 0;
}