贪心(4)选取顺序问题

目录

一,选取问题

二,集合的选取问题

CSU 1012: Prestige

CSU 1043: 克格莫

三,双端队列的选取问题

OpenJ_Bailian - 3377 Best Cow Line, Gold


一,选取问题

根据我做过的为数不多的题目,我把选取问题分为集合的选取问题、双端队列的选取问题。

二,集合的选取问题

CSU 1012: Prestige

题目:

Description

Are you watching closely?

Every great magic trick consists of three acts. The first act is called The Pledge, the magician shows you something ordinary, but of course, it probably isn't. The second act is called The Turn. The magician makes his ordinary something do something extraordinary. Now, if you're looking for the secret,you won't find it. That's why there's a third act, called The Prestige. This is the part with the twists and turns, where lives hang in the balance, and you see something shocking you've never seen before.

Li Lei and Han Meimei are magicians and they want to act the prestige. So they need to divide the props for the magic show. They have decided upon the following procedure: they choose props one by one, in turn, until all the props are chosen.

Li Lei and Han Meimei have different strategies in deciding what to choose. When faced with a choice, Li Lei always selects the prop that is most valuable to him. In case of a tie, he is very considerate and picks the one that is least valuable to Han Meimei. (Since Li Lei and Han Meimei are good friends, they know exactly how much value the other places on each prop.)

Han Meimei’s strategy, however, consists of maximizing her own final value(The total value of all the props she picked). She is also very considerate, so if multiple choices lead to the same optimal result, she prefers Li Lei to have as much final value as possible.

You are given the result that who chooses first. After Li Lei and Han Meimei have finished dividing all the props between themselves, what is the total value of the props each of them ends up with?

Input

On the first line a positive integer: the number of test cases, at most 100. After that per test case:

  • One line with an integer n(1≤n≤1,000): the number of props.

  • One line with a letter, either “L” for Li Lei or “H” for Han Meimei: the person that chooses first.

  • n lines with two integers li and hi (0≤li, hi≤1000) each: The values that Li Lei and Han Meimei assign to the i-th prop, respectively.

Output

For each test case, output one line with two integers: the value Li Lei gets and the value Han Meimei gets. Both values must be according to their own valuations.

Sample Input

3
4
L
100 80
70 80
50 80
30 50
4
L
10 1
1 10
6 6
4 4
7
H
4 1
3 1
2 1
1 1
1 2
1 3
1 4

Sample Output

170 130
14 16
9 10

题意:

有n个物品,L和H两人轮流来取

每个物品对L的价值为v1,对H的价值为v2

输入谁先取,和每个物品的价值v1v2,输出最后的结果

L的策略是每次都取v1最大的物品,如果有多个,就取其中v2最小的那个

H的策略是尽量使得最后所得总价值最大,如果有多个选择方案,就取其中v1最小的那个

思路:

贪心,先把所有物品按照L的策略进行排序

然后H每次都取v2最大的物品,但是要满足限制,就是前面若干个物品中H最多只能取一半,因为L是一直按照这个顺序往后取的

只要满足这个限制,H就能得到最优解

代码:

#include<iostream>
#include<algorithm>
using namespace std;
 
int n;
char c;
bool visit[1001], ans[1001];
 
struct node
{
	int v1, v2;
}nod[1001];
 
bool cmp(node a, node b)
{
	if (a.v1 == b.v1)return a.v2 < b.v2;
	return a.v1 > b.v1;
}
 
int getmax()
{
	int max = 0, key = 0;
	for (int i = 1; i <= n; i++)
		if (!visit[i] && max <= nod[i].v2)max = nod[i].v2, key = i;
	return key;
}
 
bool ok(int k)
{
	int s = 0;
	for (int i = 1; i <= n; i++)
	{
		if (i == k || ans[i])s++;
		if (s > (i + (c == 'H'))/2)return false;
	}
	return true;
}
 
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		cin >> n >> c;
		for (int i = 1; i <= n; i++)
		{
			cin >> nod[i].v1 >> nod[i].v2;
			visit[i] = false, ans[i] = false;
		}
		sort(nod + 1, nod + n + 1, cmp);
		int num = (n + (c == 'H')) / 2;
		visit[1] = (c == 'L');
		while (num)
		{
			int k = getmax();
			if (ok(k))ans[k] = true, visit[k] = true, num--;
			else for (int i = 1; i <= k; i++)visit[k] = true;
		}
		int s1 = 0, s2 = 0;
		for (int i = 1; i <= n; i++)
			if (ans[i])s2 += nod[i].v2; else s1 += nod[i].v1;
		cout << s1 << " " << s2 << endl;
	}
	return 0;
}

CSU 1043: 克格莫

Description

最近流行一款网游英雄联盟,类似dota的5V5对战游戏,其中一个远程攻击英雄深渊巨口·克格莫,非常强力,团战的时候站着喷,就可能拯救世界……

我们现在计算一个简单的数据,假设克格莫倒霉的遇到了对面五个人偷袭,克格莫在挂掉之前可以对敌人进行若干次攻击,友军即将包抄过来,所以克格莫只想造成尽可能高的伤害,并不追求杀掉哪一个。那么,它最高能制造多高的输出?

Input

每组数据第一行为正整数n(0 < n < 20),表示克格莫挂掉之前可以进行的攻击次数,接下来5行,代表对敌方五个人能造成的伤害。每行两个数,第一个数是敌人的生命值,第二个数是一次攻击能产生的伤害。如果一次伤害之后敌人的生命值小于0,本次伤害值依然按能够制造的伤害值计算,而下次不能再攻击这个挂掉的敌人。敌人生命值不超过5500,攻击能产生的伤害不超过550。

Output

每组数据输出一行,克格莫可以打出的最高伤害。

Sample Input

10
1000 300
5000 200
4000 500
3000 100
2000 550

Sample Output

5200

代码:

#include<iostream>
#include<algorithm>
using namespace std;
 
struct node
{
	int sm, sh;
};
 
bool cmp(node a, node b)
{
	return a.sh > b.sh;
}
 
int main()
{
	int n;
	node nod[5];
	while (cin>>n)
	{
		for (int i = 0; i < 5; i++)cin >> nod[i].sm >> nod[i].sh;
		sort(nod, nod + 5, cmp);
		int ans = 0, t;
		for (int i = 0; n; i++)
		{
			t = (nod[i].sm - 1) / nod[i].sh + 1;
			if (t > n)t = n;
			n -= t, ans += t * nod[i].sh;
		}
		cout << ans << endl;
	}
	return 0;
}

三,双端队列的选取问题

OpenJ_Bailian - 3377 Best Cow Line, Gold

题目:

FJ is about to take his N (1 <= N <= 30,000) cows to the annual "Farmer of the Year" competition. In this contest every farmer arranges his cows in a line and herds them past the judges. 

The contest organizers adopted a new registration scheme this year: simply register the initial letter of every cow in the order they will appear (e.g., If FJ takes Bessie, Sylvia, and Dora in that order, he just registers BSD). After the registration phase ends, every group is judged in increasing lexicographic order (i.e., alphabetical order) according to the string of the initials of the cows' names. 

FJ is very busy this year and has to hurry back to his farm, so he wants to be judged as early as possible. He decides to rearrange his cows, who have already lined up, before registering them. 

FJ marks a location for a new line of the competing cows. He then proceeds to marshal the cows from the old line to the new one by repeatedly sending either the first or last cow in the (remainder of the) original line to the end of the new line. When he's finished, FJ takes his cows for registration in this new order. 

Given the initial order of his cows, determine the least lexicographic string of initials he can make this way.Input* Line 1: A single integer: N 

* Lines 2..N+1: Line i+1 contains a single initial ('A'..'Z') of the cow in the ith position in the original lineOutputThe least lexicographic string he can make. Every line (except perhaps the last one) contains the initials of 80 cows ('A'..'Z') in the newline.Sample Input

6
A
C
D
B
C
B

Sample Output

ABCBCD

题意很简单,给出数列,每次取出两端的一个字符,求能得到的最小字典序字符串。

贪心即可。

代码:

#include<iostream>
using namespace std;
 
int main()
{
	int n;
	cin >> n;
	char s[30001];
	for (int i = 1; i <= n; i++)cin >> s[i];
	int left = 1, right = n, l, r;
	n = 0;
	while (left <= right)
	{
		l = left, r = right;
		while (s[l] == s[r] && l < r - 1)l++, r--;
		if (s[l] < s[r])cout << s[left++];
		else cout << s[right--];
		n++;
		if (n % 80 == 0)cout << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/nameofcsdn/article/details/112753012