2020牛客寒假算法基础集训营2 F 拿物品
题目描述
牛牛和牛可乐面前有个物品,这些物品编号是
,
,……
,每个物品有两个属性
,
。
牛牛和牛可乐会轮流从剩下的物品任意拿走一个,牛牛先选。
设牛牛选取的物品编号集合为H,牛可乐选取的物品编号的集合为T,取完之后,牛牛得分为 ,而 牛可乐得分为
。
牛牛和 牛可乐都希望自己的得分尽量比对方大(即最大化自己与对方得分的差)。
你需要求出两人都使用最优策略的情况下,最终分别会选择哪些物品,若有多种答案或输出顺序,输出任意一种。
思路
首先假设个物品已被选完,且牛牛总得分为
,牛可乐总分为
,如果两人交换一对物品,这两个物品属性分别为
 ,设
被牛牛选走了,那么交换后两人总得分分别为牛牛:
,牛可乐:
,我们要最大化
的值,那么交换后的差值
可以表示为:
,合并后得:
,如果
,那么交换后就会更大化两个人得分差值,也就是说影响差值的是同一个物品的两个属性之和,根据两个物品属性之和排序,然后依次从大到小选就可以了
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
struct p{
	ll a, b, c;
	int index;
	p(){
		
	}
	p(ll a, ll b){
		this->a = a;
		this->b = b;
	}
};
bool cmp(p& a, p& b){
	return a.c > b.c;
}
p arr[N];
int n;
vector<int> t1, t2;
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> arr[i].a;
	for (int i = 1; i <= n; i++)cin >> arr[i].b;
	for (int i = 1; i <= n; i++)arr[i].index = i;
	for (int i = 1; i <= n; i++)arr[i].c = arr[i].b + arr[i].a;
	sort(arr + 1, arr + 1 + n, cmp);
	bool f = 1;
	for (int i = 1; i <= n; i++){
		(f ? t1 : t2).push_back(arr[i].index);
		f = !f;
	}
	for (int i : t1){
		cout << i << " ";
	}
	printf("\n");
	for (int i : t2){
		cout << i << " ";
	}
	return 0;
}
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/12861961.html

                
            
        
浙公网安备 33010602011771号