这里其实用贪心做,并查集只是用来作为工具,使得速度更加快。
题意:是买卖N件东西,每件东西都有个截止时间,在截止时间之前买都可以,而每个单位时间只能买一件。问最大获利。
思路:如果购买不冲突,那么全部买下来就可以了。存在冲突,就需要取舍。显然在冲突的时候我们选择价格高的更优,如此就可以用贪心的算法。先将物品按照价格从高到底的顺序排列,购买一个就在时间点上做一个标记,只要不冲突就可以购买。 如何快速找到第一个不冲突的时间点呢,个人感觉使用并查集很好得解决了这个问题。 这里并查集的作用类似于链表指针,压缩的过程就是删掉节点的过程。从而在O(1)的时间内找到那个不冲突的点。
#include <stdio.h>
#include<algorithm>
#include<iostream>
#include <math.h>
#include<queue>
#include<string>
#include <string.h>
using namespace std;
const int maxn = 10010;
int f[maxn];
struct Node {
int p, d;
}goods[maxn];
bool cmp(Node a, Node b)//按价值从大到小排序,同则按天数降序排列
{
if (a.p != b.p)
return a.p > b.p;
else
return a.d > b.d;
}
int find(int x)
{
if (f[x] == -1)
return x;
return f[x] = find(f[x]);
}
int main()
{
int n;
while (scanf("%d", &n) !=EOF)
{
memset(f, -1, sizeof(f));
for (int i = 0; i < n; i++)
scanf("%d%d", &goods[i].p, &goods[i].d);
sort(goods, goods + n, cmp);
int ans = 0;
for (int i = 0; i < n; i++)
{
int t = find(goods[i].d);
if (t > 0)
{
ans += goods[i].p;
f[t] = t - 1;
}
}
printf("%d\n", ans);
}
return 0;
}
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The program have no BUG.
*/