皇后游戏
【引子】
还记得NOIP 2012 提高组Day1 的国王游戏吗?时光飞逝,光阴荏苒,两年
过去了。早已过时的国王游戏如今已被皇后游戏取代,请你来解决类似于国王游
戏的另一个问题。
【问题描述】
皇后有n 位大臣,每位大臣的左右手上面分别写上了一个正整数。恰逢劳动
节来临,皇后决定为n 位大臣颁发奖金,其中第i 位大臣所获得的奖金数目为第
i-1 位大臣所获得奖金数目与前i 位大臣左手上的数的和的较大值再加上第i 位
大臣右手上的数。
当然,吝啬的皇后并不希望太多的奖金被发给大臣,所以她想请你来重新安
排一下队伍的顺序,使得获得奖金最多的大臣,所获奖金数目尽可能的少。
注意:重新安排队伍并不意味着一定要打乱顺序,我们允许不改变任何一
位大臣的位置。
【输入格式】
第一行包含一个正整数T,表示测试数据的组数。
接下来T 个部分,每个部分的第一行包含一个正整数n,表示大臣的数目。
每个部分接下来n 行中,每行两个正整数,分别为ai 和bi,含义如上文所述。
【输出格式】
共T 行,每行包含一个整数,表示获得奖金最多的大臣所获得的奖金数目。
【样例输入1】
1
3
4 1
2 2
1 2
NOI 2016 模拟训练 皇后游戏
第 3 页 共 8 页
【样例输出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
55 53
94 89
53 44
3 2
39 35
26 51
5 29
【样例输出2】
360
535
对于全部测试数据满足 :1 ≤ ai, bi ≤ 109。
这道题,呵呵,看似简单,实则也有点简单。
这是题解,我猜是个人都看不懂,甚至连什么高考题都出来了。
但是感觉本人的思路还是很好的:
先对bi进行排序,因为它算的最终值中肯定有bi[i],也就是当前的bi的值,所以可以把所有数组都初始化成每个bi的值。
当然,式子中还有第i-1 位大臣所获得奖金数目与前i 位大臣左手上的数的和的较大值,所以由此可以推断出这个终值中一定有上一个的ai的值,所以最后只要比较当前的ai的值和上一个bi的值哪个大就行。
代码:
//#include#include #include #include #include <string> #include #include #include <set> #include #define mp make_pair #define fi first #define se second using namespace std; typedef long long int64; typedef pair<int,int> PII; const int MAXN=200005; int n; PII a[MAXN]; int64 dp[MAXN]; inline bool cmp(const PII &x,const PII &y) { return min(x.fi,y.se)<min(x.se,y.fi); } int main() { //freopen ("game.in","r",stdin); //freopen ("game.out","w",stdout); int testCase; for (scanf("%d",&testCase);testCase;testCase--) { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d%d",&a[i].fi,&a[i].se); sort(a+1,a+n+1,cmp); int64 s=0; for (int i=1;i<=n;i++) { s+=a[i].fi; dp[i]=max(s,dp[i-1])+a[i].se; } cout< endl; } return 0; }