题意:给出一些物品的利润和卖出的截至日期(即过了这个日期此物品就不能再卖出),每一天最多只能卖一件物品。问能获得的最大利润是多少。
解题思路:大体就是贪心吧。其中用到了类似于并查集的工具;
先按照物品的利润从大到小排序,然后从利润大的开始将其卖出时间定为截至日期之前最近的那个未被利用的一天(当然包括截止日期本天)。在寻找之前最近未被利用的一天时用到了parent这个数组,有点像并查集,及时维护能使复杂度大大降低。关于这个算法的正确性,我是这样理解的。尽量使得利润大的卖出去,找之前最近的一天是因为尽量不阻碍后继其他物品的卖出,如果仍然阻碍了其他物品卖出的话,顶多阻碍其他一个物品,而被阻碍的物品的利润一定是相等或更小的,所以这样贪心的话得到的一定是最多的利润。
代码:
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <cstring>
using namespace std;
struct point
{
int weight;
int day;
};
bool operator<(point a,point b)
{
returna.weight>b.weight;
}
point points[10001];
int parent[10001];
int getparent(int k)
{
if(k<0)
return k;
if(parent[k]==k)
return k;
returnparent[k]=getparent(parent[k]);
}
bool vis[10001];
int n;
int main()
{
while(scanf("%d",&n)==1)
{
for(int i=0;i<=10000;i++)
parent[i]=i;
memset(vis,0,sizeof vis);
for(int i=0;i<n;i++)
{
scanf("%d%d",&points[i].weight,&points[i].day);
}
sort(points,points+n);
long long ans=0;
for(int i=0;i<n;i++)
{
inttool=getparent(points[i].day);
if(tool>0)
{
vis[tool]=true;
parent[tool]=getparent(tool-1);
ans+=points[i].weight;
}
}
cout<<ans<<'\n';
}
return 0;
}