题意
给定n件商品,每件商品给定一个价值和截止时间,必须在规定的时间之前卖出商品才能获得相应的利润,如果超出规定时间利润为零。一天只能卖出一件商品,输出利润的最大值。
思路
1、贪心,因为求最大利润,所以只需把价值从大到小排序,用一个标记数组记录今天是否有商品卖出,从价格大的开始循环,如果该商品的截止时间没有被占用,就卖出该商品,如果被占用就从他的前一天往前找空闲的时间,找到空闲的时间就占用。(可以带几组例子看看) (一开始按时间从小到大排序,时间相同价格高的在前,认为这就是正确的结果提交时 wr 了。直到找了别的案例才发现这种想法是错误的。)
2、并查集、。。。没想出来,看了别人的题解才稍微理解一点。跟贪心的做法差不多。将价格从大到小排序找出最接近该商品最后期限的未被占用的一天来卖该商品。
贪心
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=10005;
struct node
{
int price,day;
}p[maxn];
bool vis[maxn];
bool cmp(node a,node b)
{
return a.price>b.price;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
scanf("%d%d",&p[i].price,&p[i].day);
sort(p,p+n,cmp);
int sum=0;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
if(!vis[p[i].day])
{
sum+=p[i].price;
vis[p[i].day]=1;
}
else
{
for(int j=p[i].day-1;j>=1;j--)
{
if(!vis[j])
{
vis[j]=1;
sum+=p[i].price;
break;
}
}
}
}
printf("%d\n",sum);
}
return 0;
}
贪心+并查集
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=10005;
int pre[maxn];
struct node
{
int x,y;
}p[maxn];
bool cmp(node a,node b)
{
return a.x>b.x;
}
int find(int x)
{
if(pre[x]==x)
return pre[x];
else
return pre[x]=find(pre[x]);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
int sum=0;
for(int i=0;i<=maxn;i++) //初始化 注意 i<maxn 而不是 n
pre[i]=i;
for(int i=0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
sort(p,p+n,cmp);
for(int i=0;i<n;i++)
{
int d=find(p[i].y); //能卖这件商品的最后一天
if(d>0) //有空闲时间 卖出商品
{
pre[d]=d-1; // 把该时间的合法时间往前推一 假设有两件商品的截止日期为同一天,截止日期那天已被价格高的用了,则价格低的那件截止日期 为 原截止日期减一
sum+=p[i].x;
}
}
printf("%d\n",sum);
}
return 0;
}