G - Supermarket POJ - 1456
題意:
有n個選擇,每次選擇權重最大的(且這次選擇不和之前的時間衝突,最優選擇,就取它所能取得最大時間)
思路:
貪心,這裏介紹兩種貪心法。
反思(並查集):
- 把題目的每個時間點轉化爲一個節點。(此時不知道題目的最大時間,所以全部初始化爲-1,find時也用-1判定)
- 每次選了一個最優的,就把那個時間點的父親變爲A-1。算是把A這個時間給用了,後面不會用
int A=find(p[i].dead);
if(A>0)
{
ans+=p[i].pa;
f[A]=A-1;//這一步
}
AC(堆優化)
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
const int maxn=1e4+10;
typedef long long ll;
struct point
{
int v;
int dead;
bool operator <(const point &x)const
{
return v<x.v;
}
}p[maxn];
bool cmp(point a,point b)
{
return a.dead>b.dead;
}
priority_queue<point>q;
int main()
{
int n;
while(~scanf("%d",&n))
{
while(!q.empty())q.pop();
int max_day=0;
For(i,1,n)
{
scanf("%d%d", &p[i].v,&p[i].dead);
max_day=max(max_day,p[i].dead);
}
sort(p+1,p+1+n,cmp);
ll ans=0,cnt=1,sum=0;
for(int i=max_day; i>=1; i--)
{
while(cnt<=n&&p[cnt].dead>=i)q.push(p[cnt++]);
if(!q.empty())
{
ans+=q.top().v;
q.pop();
}
}
printf("%lld\n",ans);
}
return 0;
}
AC(並查集,首選,複雜度低)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define mst(x,a) memset(x,a,sizeof(x))
using namespace std;
typedef long long ll;
const int maxn=1e4+10;
struct point
{
int pa,dead;
}p[maxn];
bool cmp(point a,point b)
{
return a.pa>b.pa;
}
int f[maxn];
int find(int x)
{
if(f[x]==-1)return x;
return f[x]=find(f[x]);
}
int main()
{
int n;
while(~scanf("%d", &n))
{
mst(f,-1);//未知最大時間,全部初始化爲-1,相應的find裏要改成-1
For(i,1,n)scanf("%d%d", &p[i].pa,&p[i].dead);
ll ans=0;
sort(p+1,p+1+n,cmp);
For(i,1,n)
{
int A=find(p[i].dead);
if(A>0)
{
ans+=p[i].pa;
f[A]=A-1;
}
}
printf("%lld\n", ans);
}
return 0;
}