【t072】国际象棋

Time Limit: 1 second
Memory Limit: 128 MB

【问题描述】

有N个人要参加国际象棋比赛,该比赛要进行K场对弈。每个人最多参加2场对弈,最少参加0场对弈。每个人都有一个与其他人都不
相同的等级(用一个正整数来表示)。在对弈中,等级高的人必须用黑色的棋子,等级低的人必须用白色的棋子。每一个人最多
只能用一次黑色的棋子和一次白色的棋子。为了增加比赛的可观度,观众希望K场对弈中双方的等级差的总和最小。
比如有7个选手,他们的等级分别是30; 17; 26; 41; 19; 38; 18,要进行3场比赛。最好的安排是Player 2 vs Player 7,
Player7 vs Player 5 , Player 6 vs Player 4,此时等级差的总和等于(18-17) + (19-18) + (41-38) = 5达到最小。
在90%的数据中,1≤N≤3000
在100%的数据中,1≤N≤100000
保证所以输入数据中等级的值小于108,1≤K≤N-1

【输入格式】

 第一行两个正整数N,K。
接下来有N行,第i行表示第i-1个人等级。

【输出格式】

在第一行输出最小的等级差的总和。

Sample Input

7 3
30
17
26
41
19
38
18

Sample Output

5

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=t072

【题解】

先把所有人的等级从小到大排个序;
排序之后;等级相近的两个人就会靠在一起;
而两个相近的人,它们的等级差是最小的;
这样对于
i-1,i,i+1;
可以让a[i-1]和a[i],a[i]和a[i+1]两对人来对弈;
a[i-1]< a[i]< a[i+1]
这样a[i]会对弈两次,且两次,它一次用黑棋一次用白棋,没有违反规则,然后a[i]最多对弈两次;
然后把a[i]-a[i-1]作为新的b[i],然后对b[i]再升序排,取前k个b就好;累加一下;
b[k] = a[k+1]-a[k];
取b[k]就相当于k+1和k对弈;
(相邻是最近的,这个就是贪心点吧.)

【完整代码】

#include <algorithm>
#include <cstdio>

using namespace std;

const int MAXN = 1e5+100;

int n,k;
int a[MAXN];
long long ans;

int main()
{
    //freopen("F:\rush.txt","r",stdin);
    scanf("%d%d",&n,&k);
    for (int i = 1;i <= n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    for (int i = 2;i <= n;i++)
        a[i-1] = a[i]-a[i-1];
    sort(a+1,a+1+n-1);
    for (int i = 1;i <= k;i++)
        ans+=a[i];
    printf("%I64d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626676.html