皇后游戏

皇后游戏
【引子】
还记得 NOIP 2012 提高组 Day1 的国王游戏吗?时光飞逝,光阴荏苒,两年
过去了。早已过时的国王游戏如今已被皇后游戏取代,请你来解决类似于国王游
戏的另一个问题。
【问题描述】
皇后有 n 位大臣,每位大臣的左右手上面分别写上了一个 正 整数。恰逢劳动
节来临,皇后决定为 n 位大臣颁发奖金,其中第 i 位大臣所获得的奖金数目为第
i-1 位大臣所获得奖金数目与前 i 位大臣左手上的数的和的较大值再加上第 i 位
大臣右手上的数。
形式化地讲:我们设第 i 位大臣左手上的正整数为 a i ,右手上的正整数为 b i ,
则第 i 位大臣获得的奖金数目为 c i 可以表达为:


当然,吝啬的皇后并不希望太多的奖金被发给大臣,所以她想请你来重新安
排一下队伍的顺序,使得获得奖金最多的大臣,所获奖金数目尽可能的少。
注意:重新安排队伍并不意味着一定要打乱顺 序,我们允许不改变任何一
位大臣的位置。
【输入格式】
第一行包含一个正整数 T,表示测试数据的组数。
接下来 T 个部分,每个部分的第一行包含一个正整数 n,表示大臣的数目。
每个部分接下来 n 行中,每行两个正整数,分别为 a i 和 b i ,含义如上文所述。
【输出格式】
共 T 行,每行包含一个整数,表示获得奖金最多的大臣所获得的奖金数目。
【样例输入 1】
1
3
4 1
2 2
1 2

【样例输出 1】
8
【样例说明 1】
按照 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。
【样例输入 2】
2
5
11 89
28 32
4 78
31 93
39 33
12
9 75
52 28
1 73
100 46
4 4
55 53
94 89
53 44
3 2
39 35
26 51
5 29
【样例输出 2】
360
535

 1 //#include <cmath>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <string>
 6 #include <cstdlib>
 7 #include <vector>
 8 #include <set>
 9 #include <algorithm>
10 #define mp make_pair
11 #define fi first
12 #define se second
13  
14 using namespace std;
15 
16 typedef long long int64;
17 typedef pair<int,int> PII;
18 const int MAXN=200005;
19  
20 int n;
21 PII a[MAXN];
22 int64 dp[MAXN];
23 
24 inline bool cmp(const PII &x,const PII &y)
25 {
26     return min(x.fi,y.se)<min(x.se,y.fi);
27 }
28  
29 int main()
30 {
31     //freopen ("game.in","r",stdin);
32     //freopen ("game.out","w",stdout);
33     int testCase;
34     for (scanf("%d",&testCase);testCase;testCase--)
35     {
36         scanf("%d",&n);
37         for (int i=1;i<=n;i++) scanf("%d%d",&a[i].fi,&a[i].se);
38         sort(a+1,a+n+1,cmp);
39         int64 s=0;
40         for (int i=1;i<=n;i++)
41         {
42             s+=a[i].fi;
43             dp[i]=max(s,dp[i-1])+a[i].se;
44         }
45         cout<<dp[n]<<endl;
46     }
47     return 0;
48 }

***考试的时候想的很天真哇,按左手从小到大拍个序站成一排计算值,然后再按右手从小到大排个序站成一排计算值取最小值,后来发现样例过不去哇,肿么办好叻,随手一删留下左手站队法吼吼吼好歹过了一个样例。。。。虽说最后也就五分。。。

***看了n久的题解。。好像明白了一丢丢他的意思哇,大概就是如果你站我前面你所得的值是多少,如果我站你前面比你值小,那我就站你前面好喽。。but我也不大清楚我理解是否有误叭。。。。。。

原文地址:https://www.cnblogs.com/rax-/p/8606479.html