POJ 1456 Supermarket(贪心+并查集)
Description
超市里有N个商品. 第i个商品必须在保质期(第di天)之前卖掉, 若卖掉可让超市获得pi的利润. 每天只能卖一个商品. 现在你要让超市获得最大的利润
Analyze
最主要的是贪心思想:
保质期长的商品早卖晚卖对自身无影响,但保质期短的商品却必须早卖
如此一来,贪心体现在:当前选中的最贵的商品最大限度地晚卖
若当前最贵的在保质期内:
若保质期的最后一天未被标记,则在那一天卖掉它,标记这一天
若保质期的最后一天标记了(卖了别的商品),那就在前一天卖掉它,不行再往前推一天,总之(在保质期内)越晚越好
Code
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <bitset>
#include <string>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
#define eps 1e-8
#define PI acos(-1.0)
#define ll long long
using namespace std;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
#define Close ios::sync_with_stdio(false);
void Debug(char * s)
{
cout << "------------- " << s << " -------------" << '\n';
}
typedef pair<int, int> P;
bool cmp(P a, P b)
{
return a.first > b.first;
}
int pre[10005];
int found(int x)
{
if(pre[x] == -1)
return x;
return pre[x] = found(pre[x]);
}
int main()
{
int n;
while(~scanf("%d", &n))
{
memset(pre, -1, sizeof(pre));
int price, day;
vector<P> vec;
for(int i = 0; i < n; ++i)
{
scanf("%d%d", &price, &day);
vec.push_back(P(price, day));
}
sort(vec.begin(), vec.end(), cmp);
ll ans = 0;
for(int i = 0; i < n; ++i)
{
int num = found(vec[i].second);
if(num > 0)
{
ans += vec[i].first;
pre[num] = num - 1;
}
}
cout << ans << '\n';
}
return 0;
}
found函数压缩的过程是标记的过程