2020牛客寒假算法基础集训营2 F 拿物品

题目描述

牛牛和牛可乐面前有n个物品,这些物品编号是12,……n,每个物品有两个属性a_{i}b_{i}

牛牛和牛可乐会轮流从剩下的物品任意拿走一个,牛牛先选。

设牛牛选取的物品编号集合为H,牛可乐选取的物品编号的集合为T,取完之后,牛牛得分为 \sum _{i\in H}a_{i},而 牛可乐得分为\sum _{i\in T}b_{i}

牛牛和 牛可乐都希望自己的得分尽量比对方大(即最大化自己与对方得分的差)。

你需要求出两人都使用最优策略的情况下,最终分别会选择哪些物品,若有多种答案或输出顺序,输出任意一种。

思路

首先假设n个物品已被选完,且牛牛总得分为N,牛可乐总分为M,如果两人交换一对物品,这两个物品属性分别为(a_{1},b_{1})(a_{2},b_{2}) ,设(a_{1},b_{1})被牛牛选走了,那么交换后两人总得分分别为牛牛:N-a_{1}+a_{2},牛可乐:M-b_{2}+b_{1},我们要最大化N-M(M-N)的值,那么交换后的差值N-M可以表示为:N-a_{1}+a_{2}-M+b_{2}-b_{1},合并后得:N-M-sum(a)+sum(b),如果sum(b)> sum(a),那么交换后就会更大化两个人得分差值,也就是说影响差值的是同一个物品的两个属性之和,根据两个物品属性之和排序,然后依次从大到小选就可以了

代码

#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;
}
发布了165 篇原创文章 · 获赞 11 · 访问量 9629

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/104211783