题意:
给定一批product,每个product有相应的profit和deadline,销售出一个product需要1单位的时间。
问如何销售这些商品可以使获得的利润最大。
思路:
贪心算法。
但是首先有一个误区需要注意:
每个商品的deadline,比如d=5,这个参数表明的是从1到5这个时间内都可以销售这个商品。
比如有:
d=2,p=20;
d=2,p=30;
d=1,p=2;
这样三个商品。
则销售最大值是50,而不是32。
理解这点之后其实就很直观了:
拿例子说:
7
20 1
2 1
100 2
80 2
10 3
50 10
5 20
定义数组dp[N];
整个动态规划的过程就是对dp数组进行填充。比如d=3的product可以填充在d[1],dp[2],dp[3]中的任何一个。
因为要使利润最大,则使用贪心。
所以,
当取到 20 1时,dp[1]=20 .
取到2 1时,因为2<20,舍弃不用。
当取到100 2时,将其填在dp[2]肯定是满足利润最大的情况。
而取到80 2时,将其填在dp[1]还是舍弃呢?因为80大于之前dp[1]=20。所以修改dp[1]=80。
依此类推,其实很简单,并查集都不需要用到也是可以AC的。
#include<iostream>
#include<algorithm>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
const int N=10005;
int n,ans;
struct Node
{
int p,d;
}node[N];
int dp[N];
int mn,mpos;
bool cmp(Node & a,Node & b)
{
if((a.d<b.d)||(a.d==b.d&&a.p>b.p))
return true;
return false;
}
void UpdateMin(int x)
{
int tmp1=-1,tmp2=N;
for(int j=1;j<=x;j++)//更新最小值
{
if(tmp2>dp[j])
{
tmp2=dp[j];
tmp1=j;
if(!tmp2)
break;
}
}
mpos=tmp1;
mn=tmp2;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
ans=0,mn=N,mpos=-1;
memset(node,0,sizeof(node));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&node[i].p,&node[i].d);
}
sort(node+1,node+1+n,cmp);
ans+=node[1].p;
dp[node[1].d]=node[1].p;
UpdateMin(node[1].d);
for(int i=2;i<=n;i++)
{
if(node[i].d!=node[i-1].d)
{
dp[node[i].d]=node[i].p;
ans+=node[i].p;
}
else if(node[i].p>mn)
{
ans+=node[i].p-mn;
dp[mpos]=node[i].p;
}
UpdateMin(node[i].d);
}
printf("%d\n",ans);
}
return 0;
}