本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目链接(zstuOJ/需要登录):http://47.96.116.66/problem.php?cid=3937&pid=0
题目描述
前几天,叶老师带的浙江理工大学又有同学获得国际大学生程序设计竞赛亚洲区金牌了。
大学生的竞赛与中小学竞赛略有区别,他们是3个人组队。就在你们比赛的当天,叶老师派了2个队去参加亚洲区总决赛了。
可是要如何挑选出3个默契的同学组成队伍呢?叶老师设置了一个游戏,看哪个队伍能获胜。当然,你的任务是帮助这个队伍获得胜利,每个队伍都有一定的资源。
游戏的规则如下:
叶老师给了一堆正整数写在纸牌上放在桌上,3个同学不能商量,每个人取出1张纸牌(当然不会取到同一张纸牌),然后把这纸牌上3个数加起来,本次消耗的资源是3个数的和。然后把加起来的数写在一个新的纸牌上,放回到桌上。继续第二轮......直到桌子上只剩下最后一张纸牌。每次的资源消耗和即为这个队伍的总资源消耗分。如果桌上最后纸牌数超过1张,总消耗资源直接变成9223372036854775807。
输入
第一行一个整数n(1 <= n <= 100000)
第二行n个正整数,为纸牌上的数字,每个数字不超过10000.\
输出
输出一个数,为该队伍消耗资源的最小值。
样例输入
3
9 8 7
样例输出
24
提示
保证数据不会超过64位整数
题意
有 张牌,每次任意取出 张,把 张牌的数字加起来变成新牌放入牌堆,同时记录这 张牌的数字的和。答案即为和的累加值。如果最后剩余的牌数超过 张,则输出 。
思路
先判断最后剩余的牌数超过 张的情况。简单模拟后容易发现 如果为奇数,便可以一直操作直到只剩 张牌。所以若 为偶数,输出 。
对于 为奇数的情况,由于数据规模不算大,可以使用 multiset 来模拟操作。
用贪心的思路,每次取出集合中最小的 个数,求和后放入集合,同时累加到答案即可。
代码
Time:164 ms
Memory:7596 kb
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
#define ll long long
const int maxn=1e5+7;
vector<ll> a(maxn,0);
int main(){
cin.tie(0)->sync_with_stdio(0);
int n;cin>>n;
FOR(i,1,n)
cin>>a[i];
if(n%2==0) {cout<<"9223372036854775807\n";return 0;}
multiset<ll> s(a.begin()+1,a.begin()+n+1);
ll ans=0;
while(s.size()!=1){
ll sum=0;
FOR(i,1,3){
sum+=*s.begin();
s.erase(s.begin());
}
s.insert(sum);
ans+=sum;
}
cout<<ans<<endl;
return 0;
}