题目一
解题思路
算法
(贪心,哈夫曼树,堆,优先队列) O(nlogn)
𝑂(𝑛𝑙𝑜𝑔𝑛)
经典哈夫曼树的模型,每次合并重量最小的两堆果子即可。
时间复杂度
使用小根堆维护所有果子,每次弹出堆顶的两堆果子,并将其合并,合并之后将两堆重量之和再次插入小根堆中。每次操作会将果子的堆数减一,一共操作 n−1次即可将所有果子合并成1堆。每次操作涉及到2次堆的删除操作和1次堆的插入操作,计算量是 O(logn)。因此总时间复杂度是 O(nlogn)
代码实现
cpp
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
int n;
cin >> n;
priority_queue<int, vector<int>, greater<int>> heap;
while (n -- )
{
int x;
scanf("%d", &x);
heap.push(x);
}
int res = 0;
while (heap.size() > 1)
{
int a = heap.top(); heap.pop();
int b = heap.top(); heap.pop();
res += a + b;
heap.push(a + b);
}
cout << res;
return 0;
}
题目二
解题思路
打水时间最小的人先打水,总等待时间最短,解题思路与题一相同
代码实现
cpp
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
int n;
cin >> n;
priority_queue<long long, vector<long long>, greater<long long>> heap;
while (n --)
{
long long x;
scanf("%lld", &x);
heap.push(x);
}
long long total = 0;
while(!heap.empty())
{
long long a = heap.top();
heap.pop();
total += a * heap.size();
}
cout << total;
return 0;
}
题目三
解题思路
将地址排序,取中位数作为货舱,总距离最小
为什么不是去平均数作为地址? :
代码实现
cpp
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i ++)
{
scanf("%d", &a[i]);
}
sort(a, a + n);
int loc = a[n / 2];
int dis = 0;
for (int i = 0; i < n; i ++)
{
dis += abs(a[i] - loc);
}
cout << dis;
return 0;
}
题目四
解题思路
思路: 与国王游戏的贪心策略相似, 我们先分析
每头牛的危险值 = 他前面牛的w(重量值)之和 - 自身的s(强壮值)
要使每头牛的危险值最小,根据贪心思想:
自身w值越大应该放到底部(即减小上述式中的被减数)
自身s值越大应该放到底部(即增大上述式中的减数)
所以先 yy 出一种贪心做法 每头牛的(w + s)值越大应该排在后面,即升序排序(题见多了可能就会有这种题感)。
代码实现
cpp
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 5e4 + 10;
typedef long long LL;
typedef pair<LL, LL> PII;
PII a[N];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i ++)
{
LL w, s;
scanf("%lld%lld", &w, &s);
a[i].first = w + s, a[i].second = s;
}
sort(a, a + n);
LL sum = 0, res = -1e18;
for (int i = 0; i < n; i ++)
{
sum -= a[i].second;//减去当前牛的强壮值
res = max(res, sum);//风险值最大的可能是中间的牛,所以每次都要用max才能取得全部牛中风险值最大的牛
sum += a[i].first;//相当于sum只加了当前牛的重量
}
cout << res;
return 0;
}