嗯……今天看到这题时我只在想:不是,你NOIP提高组凭什么出这么简单的题!!!除非测试点和范围很苛刻。
然后呢,我们要养成好习惯,做题前读题再看数据范围对于全部的数据,n≤10000,好那么数据范围没有坑,10000吗开个int就行了。
首先题意为“有一组数,需要合并成一个数,每次可以找两个数合成,但需要付出两个数加起来的和的代价,每次累加,到只剩一个数,问最少代价”。首先代价为两数合成之和,那么,一开始要合成较小的,才是代价最少,那么暴力思想非常简单,先sort()排序,合成最小的,然后for()循环,先合成1、2个再sort()排序,如此循环到只有一个,这里建议使用vector动态数组,合成是要舒服些,静态数组每次合成都要好一个循环,外面还有一个,sort一个,时间复杂度差不多是o(n^3)非常暴力,而且码量极大所以不建议。
暴力代码:
#include <bits/stdc++.h>
using namespace std;
vector<int> a;
int n;
int main() {
cin >> n;
for (int i = 0, x; i < n; i++) {
cin >> x;
a.push_back(x);//动态数组输入
}
int ans = 0; //合并代价计数变量
sort(a.begin(), a.end()); //动态数组排序有点不一样,要用迭代器
while (a.size() > 1) { //开始合并
a[0] += a[1]; //合并
a.erase(a.begin() + 1); //删除多余的
ans += a[0]; //累加代价
sort(a.begin(), a.end()); //数组重新排序
}
cout << ans; //打印答案变量
return 0;
}
应该是洛谷那边数据缩水了,这样也能AC,我也是真服了。
好了接下来正解应该使用优先队列的小顶堆,其他网站我的暴力代码是没AC的。
优先队列(priority_queue)是可以自定义优先级的,但STL给出了三种,优先级高的数放前面
1.时间优先级 先输入先放前面,也就是我们用的普通队列,查看队首用front()
2.大顶堆 数大放前面,定义:priority_queue<int> q;他不用写其他的,是系统默认的,查看队首用top()
3.小顶堆 数小放前面,定义:priority_queue<int, vector<int>, greater<int>> q;不是系统默认,得自己写,先写类型,在写固定容器vector<>都得这么写,在写优先级,小顶堆用greater<int>,查看队首也用top()
好,据题意得知应数小放前面,采用小顶堆,思路相同,但可省去排序,他自动排,复杂度大大降低,其它网站交也可以AC。
正解献上!
#include <bits/stdc++.h>
using namespace std;
priority_queue<int, vector<int>, greater<int>> q;//定义小顶堆
int n, a, ans;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a;
q.push(a);//同样,输入,入队
}
while (q.size() > 1) {//停止循环条件
int t = q.top();//记录队首
q.pop();//删除队首(多余的,合并后多的)
ans += q.top() + t;//记录累加代价
q.push(q.top() + t);//入队新合并的数
q.pop();//也是删除多余的(合并剩的)
}
cout << ans;//答印答案
return 0;
}
写个题解不容易,点个免费的关注或赞呗!