超市里有N个商品. 第i个商品必须在保质期(第di天)之前卖掉, 若卖掉可让超市获得pi的利润.
每天只能卖一个商品.
现在你要让超市获得最大的利润.
Input
多组数据.
每组数据第一行为一个整数N (0 <= N <= 10000), 即超市的商品数目
之后N行各有两个整数, 第i行为 pi, di (1 <= pi, di <= 10000)
Output
对于每一组数据, 输出当前条件下超市的最大利润
Sample Input
4
50 2
10 1
20 2
30 1
7
20 1
2 1
10 3
100 2
8 2
5 20
50 10
Sample Output
80
185
分析:这是道简单贪心+并查集。首先超市要获取最大利润,那么我们就把价值最大的放在最前面进行判断,当然尽可能的在他规定的最后一天卖出去最好,假设这一天已经有商品卖出去了,那就搜索前一天是否有卖出去的(类似于记忆化搜索)。
代码:
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include<iostream>
#include <map>
#include <vector>
#include <algorithm>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e5 + 10;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int pre[maxn],n;
int find(int x){
return pre[x] == x ? x : pre[x] = find(pre[x]);
}
struct node{
int val,day;
}g[maxn];
int cmp(node a,node b){
return a.val > b.val;
}
void init(){
for(int i = 0; i < maxn;i++) pre[i] = i;
}
int main(){
while(cin >> n){
for(int i = 1;i <= n;i++){
cin >> g[i].val >> g[i].day;
}
sort(g + 1,g + n + 1,cmp);
int ans = 0;
init();
for(int i = 1 ;i <= n;i++){
int temp = find(g[i].day);
if(temp == 0) continue;
else {
pre[temp] = find(temp - 1);
//压缩路径 当天已被使用后,pre的值变为前一天的根节点
ans += g[i].val;
}
}
cout << ans << endl;
}
}
同理,这题也可以用优先队列优化,思路如下:
从最大天数开始从后往前维护每天的最大值,那所有符合条件的数全部放入优先队列当中,每天只取一件,取出的就是符合条件的最大的价值的商品。
例如样例2:排序后的结果为:
5 20
50 10
10 3
100 2
8 2
20 1
2 1
因此,第20天队列中元素为 5 20,因此取5,ans += 5;
.
.
.
.
.
第2天队列中元素为 100 2
8 2
因此取100,ans += 100;
第1天队列中元素为 20 1
8 2
2 1
因此取20,ans += 20;
代码如下:
#include<queue>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include<iostream>
#include <map>
#include <vector>
#include <algorithm>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e4 + 10;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
struct node{
int val,day;
bool operator <( node a)const{
return val < a.val;
}
}pp,ans[maxn];
int cmp(node a,node b){
return a.day > b.day;
}
int solve(int n){
priority_queue<node>q;
int maxd,maxv = 0,t1,i = 0;
for(int maxd = ans[0].day; maxd > 0;maxd--){
for(;i < n &&maxd <= ans[i].day;i++){
pp.val = ans[i].val;
q.push(pp);
}
t1 = 0;
while(!q.empty() && t1 < 1){
pp = q.top();
maxv += pp.val;
q.pop();
t1++;
}
}
return maxv;
}
int main(){
int n;
while(cin >> n){
for(int i = 0;i < n;i++){
cin >> ans[i].val >> ans[i].day;
}
sort(ans,ans + n,cmp);
printf("%d\n",solve(n));
}
return 0;
}