皇后问题(题解)

皇后游戏
【引子】
还记得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 <cmath>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <set>
#include <algorithm>
#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<<dp[n]<<endl;
    }
    return 0;
}

 

posted @ 2018-03-18 16:02  Zhoier  阅读(714)  评论(0编辑  收藏  举报