题意:
给定一批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; }