我不奢望長生不死,我只想趁我活着的時候認真生活!
題目描述
牛牛舉辦了一次編程比賽,參加比賽的有3*n個選手,每個選手都有一個水平值a_i.現在要將這些選手進行組隊,一共組成n個隊伍,即每個隊伍3人.牛牛發現隊伍的水平值等於該隊伍隊員中第二高水平值。
一個隊伍三個隊員的水平值分別是3,3,3.那麼隊伍的水平值是3
一個隊伍三個隊員的水平值分別是3,2,3.那麼隊伍的水平值是3
一個隊伍三個隊員的水平值分別是1,5,2.那麼隊伍的水平值是2
爲了讓比賽更有看點,牛牛想安排隊伍使所有隊伍的水平值總和最大。
如樣例所示:
如果牛牛把6個隊員劃分到兩個隊伍
如果方案爲:
team1:{1,2,5}, team2:{5,5,8}, 這時候水平值總和爲7.
而如果方案爲:
team1:{2,5,8}, team2:{1,5,5}, 這時候水平值總和爲10.
沒有比總和爲10更大的方案,所以輸出10.
輸入描述
輸入的第一行爲一個正整數n(1 ≤ n ≤ 10^5), 表示隊伍的數量;
第二行包括3*n個整數a_i(1 ≤ a_i ≤ 10^9),表示每個參賽選手的水平值.
輸出描述
輸出一個整數表示所有隊伍的水平值總和最大值.
示例1
輸入
2
5 2 8 5 1 5
輸出
10
題目解析:
- 隊伍的水平值等於該隊伍隊員中第二高水平值,爲了所有隊伍的水平值總和最大的解法,也就是說每個隊伍的第二個值是儘可能大的值;
- 所以實際值把最大值放到最右邊,最小是放到最左邊。
解題思路:
本題的主要思路是貪心算法,貪心算法其實很簡單,就是每次選值時都選當前能看到的局部最解憂,所以這裏的貪心就是保證每組的第二個值取到能選擇的最大值就可以,我們每次儘量取最大,但是最大的數不可能是中位數,所以退而求其次,取每組中第二大的排序,然後取下標爲3n - 2,3n - 4 ,3n - 4… n+2,n位置的元素累加即可,相當下標爲[0,n-1]的n個數作每組的最左邊的數,剩下的2個數據兩個爲一組,大的值做最右邊的數,次大的做中間值,這裏就是把這個次大的值加起來。
例如
1 2 3 4 5 6 7 8 9組隊
最大的方案是:
1 8 9
2 6 7
3 4 5
即8+6+4=18。
- 先進行排序;
- 然後再把最大兩個數和最小的一個數放在一組;
- 最後就可以依次類推找出其中的最大水平值.
程序代碼
解法一
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
// IO型OJ可能會有多組測試用例,所以這裏要持續接收輸入多組測試用例。
int n;
while (cin >> n){
long long sum = 0;//這裏需要注意一下,如果將sum定義爲int類型可能會超出int的存儲範圍
vector<int> a;
a.resize(3*n);
for (int i = 0; i < (3 * n); i++){
cin >> a[i];
}
/*
排序,然後取下標爲3n - 2,3n - 4 ,3n - 4... n+2,n位置的元素累加即可,
相當下標爲[0,n-1]的n個數做每組的最左邊的數,剩下的2個數據兩個爲一組,
大的值做最右邊的數,次大的做中間值,這裏就是把這個次大的值加起來
*/
std::sort(a.begin(), a.end()); //對成員的成績進行排序
for (int i = n; i <= 3 * n - 2; i += 2){
sum += a[i];
}
cout << sum << endl;
}
}
/*
2
0 2 4 6 8 10
sum = 12
3
1 3 5 7 9 11 13 15 17
sum = 33
*/