#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define pb push_back
#define mp make_pair
#define ll long long
#define ull unsigned ll
#define db double
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define PII pair<int, int>
int main() {
int N;
ll a;
cin >> N;
priority_queue<ll, std::vector<ll>, std::greater<ll>> pq;
for (int i = 0; i < N; i++) {
cin >> a;
pq.push(a);
}
ll ans = 0;
while (pq.size() >= 2) {
ll a = pq.top();
pq.pop();
ll b = pq.top();
pq.pop();
ans += (a + b);
pq.push(a + b);
}
cout << ans << endl;
}
题目描述:
在主城站街很久之后,小萌决定不能就这样的浪费时间虚度青春,他打算去打副本。
这次的副本只有一个BOSS,而且BOSS是不需要击杀的,只需要和它比智力…….
BOSS会列出一正整数的序列,由小萌先开始,然后两个人轮流从序列的任意一端取数,取得的数累加到积分里,当所有数都取完,游戏结束。
假设小萌和BOSS都很聪明,两个人取数的方法都是最优策略,问最后两人得分各是多少。
输入
第一行:一个正整数N(2 ≤ N ≤ 100),表示序列中正整数的个数。
第二行至末尾:用空格隔开的N个正整数(1 ≤ a[i] ≤ 200)
输出
只有一行,用空格隔开的两个数,小萌的得分和BOSS的得分。
样例输入
6
4 7 2 9 5 2
样例输出
18 11
思路
一、取数游戏
双人游戏,N(2<=N<=100)个正整数序列放在一个桌子上,两人轮流从序列的两端的任意一端取数。
Alice 和Bob 轮流取数,Alice先取,两人都足够聪明,问最后两人的最高的得分是多少?
思路:s[M][M]保存先手先拿和后拿能取得的最优值;
如果先拿,可以取这个数,而且是拿左边、拿右边两者中最优的一个。
如果后拿,对方回拿左边和拿右边两者中最优的一个,那么自然留下来的就最少!
二、签到积分
Description
经过一段时期的观察,老师觉得ACM实验室的利用率太低了,于是决定雇用老套的签到积分制度,但考虑到ACMer的成长必须持之以恒,因此,专门设计了一种激励连续签到的规则。
签到积分规则如下:
1) 每天只要来到ACM实验室学习并录入指纹,即算签到成功,可获取相应的积分;若某天未签到,则当天计0个积分。
2) 连续签到时,第1天签到可获取1个积分,第2天签到可获取2个积分,……,第n天可获取n个积分。
3) 如果中途未签到,则再签到时,连续天数重新从1开始计算。
自从有了积分制度后,ACM实验室的利用率大大的提高。
有一天集训队队长在签到后向大家出了一个难题,她向大家亮出了自己的签到积分总和,然后要大家算出她至少要签到多少天,并算出从开始签到到最后签到之间至少有多少天未签到。
Input
有多组测试数据
每行输入1个一个正整数n(1<=n<=170000)
Output
与输入的测试数据相对应,每行输出2个数据,一个是签到的最少天数,一个是中途未签到的最少天数,2个数用空格隔开。
思路:有600件商品,体积为v[i],每件花费为i,用最少的花费装满背包(=最少签到天数)
体积为v[i],每件花费为1,用最少的花费装满背包(=中途未签到的最少天数+1)
每件物品无数多件,那就是一个完全背包问题(上面所求的两个子问题没有依赖关系)
如果有依赖关系,比如:n=33,33=28+3+1+1 最少签到天数是11(7+2+1+1),中途未签到最少次数为3,
33=21 + 6+6 最少签到天数是12 (6+3+3),中途未签到最少次数为2。