【“盛大遊戲杯”第15屆上海大學程序設計聯賽 K】【貪心】購買裝備

購買裝備

發佈時間: 2017年7月9日 18:17   最後更新: 2017年7月9日 21:05   時間限制: 1000ms   內存限制: 128M

最近盛大的一款遊戲傳奇世界極其火爆。遊戲玩家John,想購買遊戲中的裝備。已知遊戲的商店裏有n件裝備,第i件裝備具有屬性值ai,購買需要花費bi個金幣。John想去購買這些裝備,但是賬號中只有m個金幣,John是個很貪婪的傢伙,他想購買儘可能多的裝備。並且在保證購買到最多件裝備的情況下,他還想讓他所購買的裝備當中擁有最小屬性值的裝備屬性值儘可能大

輸入測試組數T,每組數據第一行輸入整數n(1<=n<=100000)和m(1<=m<=109), 接下來有n行,第i行有兩個數aibi(1<=ai,bi<=10000).

對於每組數據,輸出兩個數字,第一個數字代表John最多可以購買的裝備數,第二個數代表在John購買最多件裝備的前提下,所購買的裝備當中擁有最小屬性值的裝備的最大屬性值(輸入數據保證至少可以購買一件裝備)

1
2 4
3 2
2 3
1 3

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n, m;
struct A
{
	int v, c;
	bool operator < (const A & b)const
	{
		return c < b.c;
	}
}a[N];
struct Node
{
	int v, c;
	bool operator < (const Node & b)const
	{
		if (v != b.v)return v > b.v;
		return c > b.c;
	}
};
int sum[N];
priority_queue<Node>q;

int main()
{
	scanf("%d", &casenum);
	for (casei = 1; casei <= casenum; ++casei)
	{
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; ++i)
		{
			scanf("%d%d", &a[i].v, &a[i].c);
		}
		//先按照價格從小到大排序,得出數量
		sort(a + 1, a + n + 1);
		while (!q.empty())q.pop();

		//首先求得了最多能買的物品數量
		int num = 0;
		int nowCost = 0;
		for (int i = 1; i <= n; ++i)
		{
			sum[i] = sum[i - 1] + a[i].c;
			if (sum[i] <= m)
			{
				num = i;
				nowCost = sum[i];
				q.push({ a[i].v,a[i].c });
			}
		}

		//一開始把所有合法的都扔進去,然後開始考慮替換
		if (q.empty())
		{
			puts("0 0");
			continue;
		}
		for (int i = num + 1; i <= n; ++i)
		{
			Node it = q.top();
			if (a[i].v > it.v && nowCost - it.c + a[i].c <= m)
			{
				nowCost -= it.c;
				nowCost += a[i].c;
				q.pop();
				q.push({ a[i].v,a[i].c });
			}
		}
		printf("%d %d\n", num, q.top().v);
	}
	return 0;
}
/*
【題意】
http://acmoj.shu.edu.cn/problem/420/

【分析】
首先,一定要先求出最多能購買的數量
然後可以用優先隊列逐漸把當前價值低的替換掉,替換到不能替換爲止(這個可以剪枝)
也可以二分,這個比較好寫。

【時間複雜度&&優化】
O(nlogn)

*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章