【G - Supermarket】

80 篇文章 0 订阅
80 篇文章 0 订阅

思路:

  • 贪心(可加并查集优化)

  • 贪心:

    1. 选取方法:先将物品按价值从高到低排序,尽量把出售物品的时间向后放,不要影响前面的物品。
      拿最高价物品A来说:
      1. 有没有可能不选择这个最高价值的物品呢?如果不选它,那必定是在它的截止日期可以售出更高价的物品,但是它已经是最高价的啦,所以一定要卖它。
      2. 有没有可能在之前卖它可以获利更大呢?如果可以,必然是有某个物品B本来不能卖,现在能卖了,可是A和B仍然在B的deadline前占了两个位置,完全可以在A的deadline卖出A
    2. 优先队列和sort基本无区别。
  • 并查集优化:

    1. 优化查找,取消 vispar[i] 代表 i 之前的最末空闲。
    2. 每卖出一个物品,如在第 i 天卖,则 par[i] 要改成 i - 1
    3. par[i] 如果是 0 ,说明这个物品没法卖。

代码:

  • 优先队列贪心:141ms 988kB
//141ms		988kB


#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

const int maxn = 10005;

int N;
int ans;
bool vis[maxn];
struct NODE{
	int p;
	int d;
	friend bool operator < (NODE a , NODE b)
	{
		if(a.p == b.p)
			return a.d < b.d;
		return a.p < b.p;
	}
	NODE(int _p,int _d) : p(_p) , d(_d) {} ;
};
priority_queue <NODE , vector<NODE> , less<NODE> > Q;
void INIT(){
	ans = 0;
	memset(vis , 0 , sizeof(vis));
	return ;
}

int main(){
	while(cin>>N){
		INIT();
		while(N--){
			int a,b;
			scanf("%d%d" , &a , &b);
			Q.push(NODE(a,b));
		}
		while(Q.size()){
			NODE cur = Q.top() ; Q.pop() ;
			int d = cur.d;
			while(d){
				if(!vis[d]){
					vis[d] = true;
					ans += cur.p ;
					break;
				}
				d--;
			}
		}
		cout<<ans<<endl;
	} 
	return 0;
}
  • sort贪心:141ms 820kB
//141ms		820kB


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

const int maxn = 10005;

int N;
int ans;
bool vis[maxn];
struct NODE{
	int p;
	int d;
	friend bool operator < (NODE a , NODE b)
	{
		if(a.p == b.p)
			return a.d > b.d;
		return a.p > b.p;
	}
};
NODE node[maxn];

void INIT(){
	ans = 0;
	memset(vis , 0 , sizeof(vis));
	return ;
}

int main(){
	while(cin>>N){
		INIT();
		for(int i=0;i<N;i++){
			int a,b;
			scanf("%d%d" , &node[i].p , &node[i].d);
		}
		sort(node , node+N);
		for(int i=0;i<N;i++){
			int d = node[i].d ;
			while(d){
				if(!vis[d]){
					vis[d] = true;
					ans += node[i].p;
					break;
				}
				d--;
			}
		}
		cout<<ans<<endl;
	} 
	return 0;
}
  • 并查集优化:63ms 1020kB
//63ms		1020kB


#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

const int maxn = 10005;

int N;
int ans;
struct NODE{
	int p;
	int d;
	friend bool operator < (NODE a , NODE b)
	{
		if(a.p == b.p)
			return a.d < b.d ;
		return a.p < b.p ;
	}
	NODE(int p , int d) : p(p) , d(d) {} ;
};
priority_queue <NODE , vector<NODE> , less<NODE> > Q;
int par[maxn];

void INIT(){
	ans = 0;
	memset(par , -1, sizeof(par));
	return ;
}

int FIND(int i){
	return par[i] == -1 ? i : par[i] = FIND(par[i]);
}

int main(){
	while(cin>>N){
		INIT();
		int a, b;
		for(int i=1;i<=N;i++){
			scanf("%d%d" , &a , &b);
			Q.push(NODE(a,b));
		}
		while(Q.size()){
			NODE cur = Q.top() ; Q.pop() ;
			int d = cur.d;
			int pard = FIND(d);
			if(!pard)
				;
			else{
				par[pard] = pard - 1;
				ans += cur.p;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值