1、题目描述
题目背景
还记得 NOIP 2012 提高组 Day1 的国王游戏吗?时光飞逝,光阴荏苒,两年过去了。国王游戏早已过时,如今已被皇后游戏取代,请你来解决类似于国王游戏的另一个问题。
题目描述
皇后有 n 位大臣,每位大臣的左右手上面分别写上了一个正整数。恰逢国庆节来临,皇后决定为 n 位大臣颁发奖金,其中第 i 位大臣所获得的奖金数目为第i-1 位大臣所获得奖金数目与前 i 位大臣左手上的数的和的较大值再加上第 i 位大臣右手上的数。
形式化地讲:我们设第 i 位大臣左手上的正整数为 ai,右手上的正整数为 bi,则第 i 位大臣获得的奖金数目为 ci可以表达为:
当然,吝啬的皇后并不希望太多的奖金被发给大臣,所以她想请你来重新安排一下队伍的顺序,使得获得奖金最多的大臣,所获奖金数目尽可能的少。
注意:重新安排队伍并不意味着一定要打乱顺序,我们允许不改变任何一位大臣的位置。
输入格式
第一行包含一个正整数 T,表示测试数据的组数。
接下来 T 个部分,每个部分的第一行包含一个正整数 n,表示大臣的数目。
每个部分接下来 n 行中,每行两个正整数,分别为 ai和 bi,含义如上文所述。
输出格式
共 T 行,每行包含一个整数,表示获得奖金最多的大臣所获得的奖金数目。
输入输出样例
输入 #1 复制
1
3
4 1
2 2
1 2
输出 #1 复制
8
输入 #2 复制
2
5
85 100
95 99
76 87
60 97
79 85
12
9 68
18 45
52 61
39 83
63 67
45 99
52 54
82 100
23 54
99 94
63 100
52 68
输出 #2 复制
528
902
说明/提示
按照 1、2、3 这样排列队伍,获得最多奖金的大臣获得奖金的数目为 10;
按照 1、3、2 这样排列队伍,获得最多奖金的大臣获得奖金的数目为 9;
按照 2、1、3 这样排列队伍,获得最多奖金的大臣获得奖金的数目为 9;
按照 2、3、1 这样排列队伍,获得最多奖金的大臣获得奖金的数目为 8;
按照 3、1、2 这样排列队伍,获得最多奖金的大臣获得奖金的数目为 9;
按照 3、2、1 这样排列队伍,获得最多奖金的大臣获得奖金的数目为 8。
当按照 3、2、1 这样排列队伍时,三位大臣左右手的数分别为:
(1, 2)、(2, 2)、(4, 1)
第 1 位大臣获得的奖金为 1 + 2 = 3;
第 2 位大臣获得的奖金为 max{3, 3} + 2 = 5;
第 3 为大臣获得的奖金为 max{5, 7} + 1 = 8。
对于全部测试数据满足:T <= 10, 1 <= n <= 20000,1 < ai,bi < 10^9
2、问题分析
这题乍一看和P1080 国王的游戏很像啊,因此咱还是根据题意先用数学的思想建模推导一番:
设第i个大臣的收益为ci,左手金额为ai,右手金额为bi,第j个大臣的收益为cj,左手金额为aj,右手金额为bj,第i个大臣前i-1个人的金额之和为x,第i-1个大臣的收益为y。
左手金额 右手金额 前i-1个人 x / 第i个大臣 ai bi 第j个大臣 aj bj
根据题目的要求,有:
ci = max{y,x+ai} + bi
cj = max{ci,x+ai+aj}+bj
= max{max{y,x+ai} + bi,x+ai+aj}+bj
= max{y+bi+bj,x+ai+bi+bj,x+ai+aj+bj}
此时两位大臣的中的较大收益记为C1, 显然
C1 = cj = max{y+bi+bj,x+ai+bi+bj,x+ai+aj+bj}
因为我们是要研究排列的方式对整体最大收益的影响,因而改变第i个大臣和第j个大臣的排列
左手金额 右手金额 前i-1个人 x / 第j个大臣 aj bj 第i个大臣 ai bi
根据题目的要求,有:
cj = max{y,x+aj} + bj
ci = max{cj,x+ai+aj}+bi
= max{max{y,x+aj} + bj,x+ai+aj}+bi
= max{y+bi+bj,x+aj+bi+bj,x+ai+aj+bi}
此时两位大臣的中的较大收益记为C2, 显然
C2 = ci = max{y+bi+bj,x+aj+bi+bj,x+ai+aj+bi}
设C1为C1、C2中的较小者,则 C1 <= C2
max{y+bi+bj,x+ai+bi+bj,x+ai+aj+bj}
<= max{y+bi+bj,x+aj+bi+bj,x+ai+aj+bi}
=>
max{x+ai+bi+bj,x+ai+aj+bj}
<=max{x+aj+bi+bj,x+ai+aj+bi}
=>
max{ai+bi+bj,ai+aj+bj}<=max{aj+bi+bj,ai+aj+bi}
=>
max{bi,aj}+ai+bj<=max{bj,ai}+aj+bi
=>
max{bi,aj}-aj-bi <= max{bj,ai}-ai-bj
=>
-min{aj,bi}<=-min{ai,bj}
=>
min{ai,bj}<=min{aj,bi}
同理,设C2为C1、C2中的较小,可得到类似推论。
但这题与P1080国王的游戏不同的是,ai,bi,aj,bj之间没有明显的直接大小关系,而直接用式子min{ai,bj}<=min{aj,bi}进行排序,会容易出问题,所以我们需要分情况讨论ai,bi,aj,bj之间的大小关系。
考虑到直接进行分类判断情况过于冗杂,故引入变量d = a - b/|a-b|,表示每个大臣左右手金额大小关系,d的值有三种情况,
①、d = 1, 即a > b,
②、d = 0, 即a = b,
③、d = -1, 即a < b
此时情况可分为以下三种:
(1)、di < dj
(2)、di > dj
(3)、di = dj
对于情况(1):因为di<dj,所以ai-bi<aj-bj,设此时ai<aj,bi>bj(因为令ai<aj,bi>bj可使得ai-bi<aj-bj),为满足式子min{ai,bj}<=min{aj,bi},令ai<bi,bj<aj,即di=ai-bi<0,dj=aj-bj>0,满足di<dj,按di<dj排序即可。
对于情况(2):因为di>dj,所以ai-bi>aj-bj,设此时ai>aj,bi<bj,为满足式子min{ai,bj}<=min{aj,bi},令ai<bi,bj<aj,即di=ai-bi<0,dj=aj-bj>0,满足di<dj,按di<dj排序即可。
对于情况(3):因为di=dj,
①设di < 0,dj < 0,即ai < bi, aj < bj,为满足式子min{ai,bj}<=min{aj,bi},则ai<aj,按ai<aj排序即可。
②、设di = 0,dj = 0,即ai=bi,aj=bj,此时式子min{ai,bj}<=min{aj,bi},变成ai<aj,按ai<aj排序即可。
③、设di > 0, dj > 0,即ai > bi, aj > bj,为满足式子min{ai,bj}<=min{aj,bi},则bi>bj,按bi>bj排序即可。
3、算法源码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct hand{
ll a;
ll b;
ll d;
} h[20001];
ll c[20001];
bool cmp(hand h1,hand h2){
if(h1.d != h2.d) return h1.d < h2.d;
if(h1.d <= 0) return h1.a < h2.a;
return h1.b > h2.b;
}
int main(){
int T;
cin >> T;
while(T--){
int n;
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> h[i].a >> h[i].b;
if(h[i].a > h[i].b) h[i].d = 1;
else if(h[i].a == h[i].b) h[i].d = 0;
else h[i].d = -1;
}
sort(h + 1, h + 1 + n, cmp);
for(int i = 1; i <= n; i++){
//因为前面已经排完序了,所以不需要用到单个a的值,所以可以用前缀和计算
h[i].a += h[i-1].a;
c[i] = max(c[i-1],h[i].a)+ h[i].b;
}
cout << c[n] << endl;
}
}