4 50 2 10 1 20 2 30 1 7 20 1 2 1 10 3 100 2 8 2 5 20 50 10Sample Output
80 185Hint
题意:有·N个商品,价格为p,保质期为d。只能在保质期之前(包含d)卖出,并且每天只能卖出一个商品。求最大的利润。
题解:先安排价格高的商品,最好是放在保质期d那一天,如果已经被占(商品价格肯定比它高),往前找。类似并查集找祖宗的过程。注:f[i]只能初始化为-1;如果初始化为0,当保质期为一天有多个商品时,会出现重复计算。
并查集+贪心思想:
#include
#include
#include
using namespace std;
int n;
int f[10200];
struct note
{
int p,d;
} q[10100];
int cmp(note a,note b)
{
return a.p>b.p;
}
int getf(int v)
{
if(f[v]==-1)return v; //如果当天没被占,就放在当天卖
else
{
f[v]=getf(f[v]); //如果当天被占,就往前找(祖宗)。
return f[v];
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(f,-1,sizeof(f)); //f[i]不能·等于·i;天数是不连贯的,和商品标号也没有也无关系。
int maxn=-1;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&q[i].p,&q[i].d);
}
sort(q+1,q+n+1,cmp);
int sum=0;
for(int i=1; i<=n; i++)
{
int t=getf(q[i].d);//返回第几天卖
if(t>0) //天数为<=0?不存在的,如果如此,这件商品,只能丢弃了。
{
sum+=q[i].p;
f[t]=t-1; //t天被占用后,它的祖宗应该指向前一天。
}
}
printf("%d\n",sum);
}
return 0;
}
贪心:思路相同
#include
#include
#include
using namespace std;
int n;
int vis[10200];
struct note
{
int p,d;
}q[10100];
int cmp(note a,note b)
{
return a.p>b.p;
}
int main()
{
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&q[i].p,&q[i].d);
}
sort(q+1,q+n+1,cmp);
int sum=0;
for(int i=1;i<=n;i++)
{
if(!vis[q[i].d])
{
vis[q[i].d]=1;
sum+=q[i].p;
}
else
{
for(int j=q[i].d-1;j>=1;j--)
{
if(!vis[j])
{
vis[j]=1;
sum+=q[i].p;
break;
}
}
}
}
printf("%d\n",sum);
}
return 0;
}