拿物品(贪心)

链接:https://ac.nowcoder.com/acm/contest/3003/F
来源:牛客网

题目描述

牛牛和 牛可乐 面前有 n 个物品,这些物品编号为 1,2,…,n,每个物品有两个属性 ai,bi 。
牛牛与 牛可乐会轮流从剩下物品中任意拿走一个, 牛牛先选取。
设 牛牛选取的物品编号集合为 H,牛可乐选取的物品编号的集合为 T,取完之后,牛牛 得分为 i∈Hai;而 牛可乐得分为 i∈Tbi
牛牛和 牛可乐都希望自己的得分尽量比对方大(即最大化自己与对方得分的差)。
你需要求出两人都使用最优策略的情况下,最终分别会选择哪些物品,若有多种答案或输出顺序,输出任意一种。

输入描述:

第一行,一个正整数 n,表示物品个数。
第二行,n 个整数 a1,a2,…,an,表示 n 个物品的 A 属性。
第三行,n 个整数 b1,b2,…,bn,表示 n 个物品的 B 属性。
保证 2≤n≤2×1050≤ai,bi≤109

输出描述:

输出两行,分别表示在最优策略下 牛牛和 牛可乐各选择了哪些物品,输 出物品编号。

输入

3
8 7 6
5 4 2

输出

1 3
2

说明

3 1
2

也会被判定为正确

假设物品已经被选完,此时牛牛选择的物品 A 属性的价值和是 N , 牛可乐选择的物品 B 属性价值和是 M 。

如果 牛牛的 (a1,b1)物品与 牛可乐的 (a2,b2)交换,则 N′=N−a1+a2,M′=M+b1−b2,对于牛牛(目标是最大化 N−M )来说会变得更优仅当 a1+b1<a2+b2N′−M′>N−M 化简就能得到),对于牛可乐也一样。

所以两人都会优先选择 ai+bi最大的物品。

将物品按照两个属性的和从大到小排序,依次分给两人即可。

除排序时间复杂度 O(n) 。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <stack>
 9 #include <queue>
10 #include <set>
11 #include <map>
12 #include <sstream>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const int mod=1e9+7;
16 const int maxn=1e4+10;
17 using namespace std;
18 
19 struct node
20 {
21     int x,y;
22     int pos;
23 }PT[200005];
24 
25 vector<int> vt[2];//记录答案 
26 
27 bool cmp(node a,node b)
28 {
29     return a.x+a.y > b.x+b.y;
30 }
31 
32 int main()
33 {
34     #ifdef DEBUG
35     freopen("sample.txt","r",stdin);
36     #endif
37     
38     int n;
39     scanf("%d",&n);
40     for(int i=1;i<=n;i++)
41     {
42         scanf("%d",&PT[i].x);
43         PT[i].pos=i;//记录位置 
44     }
45     for(int i=1;i<=n;i++)
46         scanf("%d",&PT[i].y);
47     sort(PT+1,PT+1+n,cmp);
48     for(int i=1;i<=n;i++)
49         vt[i%2].push_back(PT[i].pos);
50     for(int k=1;k>=0;k--)
51     {
52         for(int i=0;i<vt[k].size();i++)
53             printf(i==vt[k].size()-1?"%d
":"%d ",vt[k][i]);
54     }
55     
56     return 0;
57 }

-

原文地址:https://www.cnblogs.com/jiamian/p/12271718.html