14012: 【原4012】合并果子
题目
题目描述
author: noip2004 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4012
Description
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。
Input Format
一共两行: 第一行是一个整数n(1<=n<=10000),表示果子的种类数。 第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i种果子的数目。
Output Format
一个整数,也就是最小的体力耗费值。输入数据保证这个值小于2^31。
Sample Input
3
1 2 9
Sample Output
15
数据范围
对于30%的数据,保证有n<=1000: 对于50%的数据,保证有n<=5000; 对于全部的数据,保证有n<=10000。
Limits
时间限制:1000ms
BugenZhao's solution
//
// Created by BugenZhao on 2019/5/8.
//
//
// Created by BugenZhao on 2019/4/5.
//
#ifndef SBL_BPRIORITYQUEUE_H
#define SBL_BPRIORITYQUEUE_H
namespace bpq {
template<typename Item>
struct greater {
bool operator()(const Item &a, const Item &b) {
return a > b;
}
};
template<typename Item>
struct less {
bool operator()(const Item &a, const Item &b) {
return a < b;
}
};
}
template<typename Item, typename Comparator = bpq::greater<Item>>
class BPriorityQueue {
Comparator comparator;
Item *pq;
int N = 0;
int maxN;
int minN;
private:
bool cmp(int i, int j) {
return comparator(pq[i], pq[j]);
}
void exch(int i, int j) {
Item item = pq[i];
pq[i] = pq[j];
pq[j] = item;
}
void resize(int newMaxN) {
Item *old = pq;
pq = new Item[newMaxN + 1];
int length = newMaxN > maxN ? maxN : newMaxN;
for (int i = 1; i <= length; ++i) {
pq[i] = old[i];
}
delete[] old;
}
void swim(int k) {
while (k > 1 && cmp(k, k / 2)) {
exch(k / 2, k);
k /= 2;
}
}
void sink(int k) {
int j;
while (2 * k <= N) {
j = 2 * k;
j += (j < N && cmp(j + 1, j));
if (cmp(j, k)) {
exch(k, j);
k = j;
} else break;
}
}
public:
BPriorityQueue() {
this->maxN = 1;
this->minN = -1;
pq = new Item[1 + 1];
}
BPriorityQueue(int maxN) {
this->maxN = maxN;
this->minN = maxN;
pq = new Item[maxN + 1];
}
BPriorityQueue(const Item *pq, int size) {
maxN = N = size;
minN = N;
this->pq = new Item[size + 1];
for (int i = 1; i <= N; ++i) {
this->pq[i] = pq[i - 1];
}
for (int k = N / 2; k >= 1; --k) {
sink(k);
}
}
bool isEmpty() {
return N == 0;
}
int size() {
return N;
}
void insert(const Item &item) {
if (N == maxN)
resize(2 * N);
pq[++N] = item;
swim(N);
}
Item pop() {
if (N <= maxN / 4) {
if (maxN / 2 >= minN) resize(maxN / 2);
else resize(minN);
}
Item item = pq[1];
exch(1, N);
--N;
sink(1);
return item;
}
const Item &peek() {
return pq[1];
}
virtual ~BPriorityQueue() {
delete[] pq;
}
};
#endif //SBL_BPRIORITYQUEUE_H
#include <iostream>
#include <string>
using std::ios, std::cin, std::cout, std::endl, std::string;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
int tmp;
BPriorityQueue<int, bpq::less<int>> pq(n);
for (int i = 0; i < n; ++i) {
cin >> tmp;
pq.insert(tmp);
}
int a, b;
int ans = 0;
while (pq.size() >= 2) {
a = pq.pop();
b = pq.pop();
pq.insert(a + b);
ans += a + b;
}
cout << ans << endl;
return 0;
}
ligongzzz's solution
#include "iostream"
using namespace std;
template <class T>
class mVector {
T** vector_data = nullptr;
unsigned int size = 0;
unsigned int capacity = 0;
public:
//构造函数
mVector() = default;
mVector(unsigned int _size) :size(_size) {
capacity = _size * 2;
vector_data = new T * [capacity] {nullptr};
}
mVector(unsigned int _size, const T& val) :size(_size) {
capacity = _size * 2;
vector_data = new T * [capacity] {nullptr};
for (unsigned int i = 0; i < _size; ++i)
vector_data[i] = new T(val);
}
mVector(const mVector<T> & _vector) :size(_vector.size), capacity(_vector.capacity) {
vector_data = new T * [capacity] {nullptr};
for (int i = 0; i < size; ++i)
vector_data[i] = new T(*_vector.vector_data[i]);
}
//析构函数
~mVector() {
for (unsigned int i = 0; i < size; ++i)
delete vector_data[i];
delete[] vector_data;
}
//迭代器
class iterator {
T** pos = nullptr;
friend iterator mVector<T>::begin();
friend iterator mVector<T>::end();
friend void mVector<T>::erase(const iterator& val);
public:
iterator() = default;
iterator(const iterator& other) {
pos = other.pos;
}
iterator& operator++() {
++pos;
return *this;
}
iterator operator++(int) {
iterator temp(*this);
++pos;
return temp;
}
iterator& operator--() {
--pos;
return *this;
}
iterator operator--(int) {
iterator temp(*this);
--pos;
return temp;
}
bool operator==(const iterator& other) const {
return pos == other.pos;
}
bool operator!=(const iterator& other) const {
return pos != other.pos;
}
iterator& operator=(const iterator& other) {
pos = other.pos;
return *this;
}
T& operator*() const {
return **pos;
}
};
//增加元素
void push_back(const T & val) {
if (size < capacity)
vector_data[size++] = new T(val);
else {
T** temp_data = new T * [(capacity + 1) * 2]{ nullptr };
for (unsigned int i = 0; i < size; ++i)
temp_data[i] = vector_data[i];
temp_data[size++] = new T(val);
capacity = (capacity + 1) * 2;
delete[] vector_data;
vector_data = temp_data;
}
}
//删除末尾
void pop_back() {
delete vector_data[size];
vector_data[size--] = nullptr;
}
//清空
void clear() {
for (unsigned int i = 0; i < size; ++i) {
delete vector_data[i];
vector_data[i] = nullptr;
}
size = 0;
}
//删除
void erase(const iterator & val) {
delete* val.pos;
for (auto p = val.pos; p != vector_data + size - 1; ++p)
* p = *(p + 1);
--size;
vector_data[size] = nullptr;
}
//重载运算符
T & operator[](const unsigned int& pos) {
return *vector_data[pos];
}
iterator begin() {
iterator temp;
temp.pos = vector_data;
return temp;
}
iterator end() {
iterator temp;
temp.pos = vector_data + size;
return temp;
}
};
template <class T>
class myPriorityQueue {
public:
mVector<T> queueData;
unsigned int sizeOfQueue = 0;
bool(*cmp)(T a, T b) = [](T a, T b) {return a < b; };
//向下过滤
void percolateDown(unsigned int pos) {
while (pos * 2 <= sizeOfQueue) {
if (pos * 2 + 1 > sizeOfQueue) {
//交换
if (cmp(queueData[pos * 2], queueData[pos])) {
auto temp = queueData[pos * 2];
queueData[pos * 2] = queueData[pos];
queueData[pos] = temp;
}
break;
}
else {
bool minNum = cmp(queueData[pos * 2 + 1], queueData[pos * 2]);
if (cmp(queueData[pos * 2 + minNum], queueData[pos])) {
auto temp = queueData[pos * 2 + minNum];
queueData[pos * 2 + minNum] = queueData[pos];
queueData[pos] = temp;
pos = pos * 2 + minNum;
}
else break;
}
}
}
//构建
myPriorityQueue() {
queueData.clear();
queueData.push_back((T)0);
sizeOfQueue = 0;
}
//compare函数返回父结点a与孩子结点b的关系正确与否
myPriorityQueue(bool(*compare)(T a, T b)) :cmp(compare) {
queueData.clear();
queueData.push_back(*new T);
sizeOfQueue = 0;
}
//根据数组建立堆
void buildHeap(T* eleData, unsigned int eleNum) {
queueData.clear();
sizeOfQueue = eleNum;
queueData.push_back(*new T);
for (unsigned int i = 1; i <= eleNum; i++)
queueData.push_back(eleData[i - 1]);
//向下过滤
for (unsigned int pos = eleNum / 2; pos > 0; pos--)
percolateDown(pos);
}
void refresh() {
//向下过滤
for (unsigned int pos = size() / 2; pos > 0; pos--)
percolateDown(pos);
}
//判断是否空
bool empty() {
return sizeOfQueue == 0;
}
//返回队列大小
auto size() {
return sizeOfQueue;
}
//入队
void push(const T & input) {
sizeOfQueue++;
queueData.push_back(input);
//向上过滤
for (auto i = sizeOfQueue; i > 1; i = i / 2) {
//判断是否比父结点更小
if (cmp(queueData[i], queueData[i / 2])) {
//交换
auto temp = queueData[i];
queueData[i] = queueData[i / 2];
queueData[i / 2] = temp;
}
else break;
}
}
//队列最前
T top() {
return queueData[1];
}
//出队
T pop() {
auto temp = queueData[1];
queueData[1] = queueData[sizeOfQueue--];
queueData.pop_back();
percolateDown(1);
return temp;
}
};
int weight[20000] = { 0 };
int main() {
//ios::sync_with_stdio(false);
//cin.tie(NULL);
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> weight[i];
//排除特殊情况
if (n == 1) {
cout << weight[0];
return 0;
}
myPriorityQueue<int> fruit;
fruit.buildHeap(weight, n);
long long ans=0;
//不断循环
while (fruit.sizeOfQueue > 2) {
if (fruit.queueData[2] <= fruit.queueData[3]) {
fruit.queueData[2] += fruit.queueData[1];
ans += fruit.queueData[2];
fruit.percolateDown(2);
}
else {
fruit.queueData[3] += fruit.queueData[1];
ans += fruit.queueData[3];
fruit.percolateDown(3);
}
//剔除最小的元素
fruit.pop();
}
ans += fruit.queueData[1] + fruit.queueData[2];
cout << ans;
return 0;
}
Neight99's solution
#include <iostream>
using namespace std;
const int maxN = 1e5 + 100;
template <class Type>
class priorityQueue {
private:
int currentSize;
Type *array;
int maxSize;
void doubleSpace();
// void buildHeap();
void percolateDown(int);
public:
priorityQueue(int capacity = maxN);
// priorityQueue(const Type data[],int size);
~priorityQueue();
bool isEmpty() const;
void enQueue(const Type &x);
Type deQueue();
Type getHead() const;
};
template <class Type>
priorityQueue<Type>::priorityQueue(int capacity)
: maxSize(capacity), currentSize(0) {
array = new Type[capacity];
}
template <class Type>
priorityQueue<Type>::~priorityQueue() {
delete[] array;
}
template <class Type>
bool priorityQueue<Type>::isEmpty() const {
return currentSize == 0;
}
template <class Type>
Type priorityQueue<Type>::getHead() const {
return array[1];
}
template <class Type>
void priorityQueue<Type>::enQueue(const Type &x) {
if (currentSize == maxSize - 1) {
doubleSpace();
}
int hole = ++currentSize;
for (; hole > 1 && x < array[hole / 2]; hole /= 2) {
array[hole] = array[hole / 2];
}
array[hole] = x;
}
template <class Type>
Type priorityQueue<Type>::deQueue() {
Type minItem;
minItem = array[1];
array[1] = array[currentSize--];
percolateDown(1);
return minItem;
}
template <class Type>
void priorityQueue<Type>::percolateDown(int hole) {
int child;
Type tmp = array[hole];
for (; hole * 2 <= currentSize; hole = child) {
child = hole * 2;
if (child != currentSize && array[child + 1] < array[child]) {
child++;
}
if (array[child] < tmp) {
array[hole] = array[child];
} else {
break;
}
}
array[hole] = tmp;
}
template <class Type>
void priorityQueue<Type>::doubleSpace() {
Type *tmp = array;
maxSize *= 2;
array = new Type[maxSize];
for (int i = 0; i < currentSize; i++) {
array[i] = tmp[i];
}
delete[] tmp;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int N, tmp1, tmp2, tmp3;
long long strength = 0;
priorityQueue<int> fruits;
cin >> N;
for (int i = 0; i < N; i++) {
cin >> tmp1;
fruits.enQueue(tmp1);
}
for (int i = 0; i < N - 1; i++) {
tmp1 = fruits.deQueue();
tmp2 = fruits.deQueue();
tmp3 = tmp1 + tmp2;
fruits.enQueue(tmp3);
strength += tmp3;
}
cout << strength;
}
q4x3's solution
/**
* 最小堆 + 哈夫曼
* 每次把最小的两个取出来加到一起
* 加入ans
* 并放回堆中
**/
#include <iostream>
#include <stdio.h>
using namespace std;
long long int N, F[10233], ans;
void down(long long int rt, long long int size) {
long long int tmp = F[rt];
if((rt << 1) > size) return;
else if((rt << 1 | 1) > size) {
if(tmp > F[rt << 1]) {
F[rt] = F[rt << 1];
F[rt << 1] = tmp;
}
return;
} else {
long long int chi1 = F[rt << 1], chi2 = F[rt << 1 | 1];
if(chi1 < tmp && chi1 <= chi2) {
F[rt] = chi1;
F[rt << 1] = tmp;
down(rt << 1, size);
} else if(chi2 < tmp && chi2 <= chi1) {
F[rt] = chi2;
F[rt << 1 | 1] = tmp;
down(rt << 1 | 1, size);
}
}
}
void build() {
for(long long int i = N / 2;i > 0;-- i) {
down(i, N);
}
}
void op(long long int size) {
long long int head = F[1];
F[1] = F[size];
down(1, size - 1);
F[1] += head; ans += F[1];
down(1, size - 1);
}
int main() {
scanf("%lld", &N);
for(long long int i = 1;i <= N;++ i)
scanf("%lld", &F[i]);
build();
for(long long int i = 0;i < N - 1;++ i) {
op(N - i);
}
cout << ans << endl;
return 0;
}
skyzh's solution
#include <iostream>
using namespace std;
#include <stdio.h>
template<typename T>
struct Heap {
T *data;
int cap, len;
Heap(int cap = 1024) : cap(cap + 1), len(0) {
data = new T[cap];
}
Heap(const Heap& that) : cap(that.cap), len(that.len) {
data = new T[cap];
memcpy(data, that.data, sizeof(T) * cap);
}
~Heap() { delete[] data; }
void push(const T &x) {
data[++len] = x;
swim(len);
}
T pop() {
swap(data[1], data[len--]);
sink(1);
return data[len + 1];
}
void top() {
return data[1];
}
bool less(int a, int b) {
if (a > len || b > len) return false;
return data[a] < data[b];
}
void swim(int idx) {
int _idx;
while (idx > 1 && less(idx, _idx = idx / 2)) {
swap(data[idx], data[_idx]);
idx = _idx;
}
}
void sink(int idx) {
int _idx;
while ((_idx = 2 * idx) <= len) {
if (_idx < len && less(_idx + 1, _idx)) _idx++;
if (less(idx, _idx)) break;
swap(data[idx], data[_idx]);
idx = _idx;
}
}
bool empty() {
return len == 0;
}
};
int main() {
int n;
int x[20000];
long long sum = 0;
Heap <int> heap(20000);
cin >> n;
int _data;
for (int i = 0; i < n; i++) {
cin >> _data;
heap.push(_data);
}
for (int i = 0; i < n - 1; i++) {
int op1 = heap.pop(), op2 = heap.pop();
int s = op1 + op2;
heap.push(s);
sum += s;
}
cout << sum << endl;
return 0;
}
victrid's solution
#include <iostream>
using namespace std;
long long strage[400005];
int treesize;
void swap(long long& a1, long long& a2) {
if (a1 != a2) {
a1 ^= a2;
a2 ^= a1;
a1 ^= a2;
}
return;
};
void insert(long long i) {
strage[++treesize] = i;
int x = treesize;
while (x != 1) {
if (strage[x] < strage[x >> 1]) {
swap(strage[x], strage[x >> 1]);
x >>= 1;
} else
break;
}
return;
}
long long pop() {
swap(strage[1], strage[treesize]);
treesize--;
int i = 2;
while (i <= treesize) {
if ((i | 1) <= treesize && strage[i | 1] < strage[i])
i |= 1;
if (strage[i] < strage[i >> 1]) {
swap(strage[i], strage[i >> 1]);
i <<= 1;
} else
break;
}
return strage[treesize + 1];
}
int main() {
int n, x, y;
long long ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
insert(x);
}
while (treesize > 1) {
x = pop();
y = pop();
ans += x + y;
insert(x + y);
}
printf("%lld", ans);
return 0;
}
WashSwang's solution
#include <iostream>
#include <cstdio>
using namespace std;
int rmargin,lmargin,dmargin,m,n,p,q,t,x,sx,sy,patx[1000001],paty[1000001],map[1001][1001],num,pnum;
bool flag;
int main() {
scanf("%d",&t);
for (int i=0;i<t;++i){
flag=true;
num=0;
lmargin=0;
rmargin=0;
dmargin=0;
pnum=0;
scanf("%d%d%d%d",&m,&n,&p,&q);
for (int j=0;j<m;++j)
for (int k=0;k<n;++k) {
scanf("%d", &map[j][k]);
if (map[j][k]) pnum++;
}
for (int j=0;j<p;++j)
for (int k=0;k<q;++k)
{
scanf("%d",&x);
if (x){
if (num==0) {
sx=j;
sy=k;
num++;
}
else{
patx[num]=j-sx;
paty[num]=k-sy;
if (paty[num]<0)
lmargin=max(lmargin,paty[num]);
rmargin=max(rmargin,paty[num]);
dmargin=max(dmargin,patx[num]);
num++;
}
}
}
for (int j=0;j<m-dmargin;++j){
for (int k=lmargin;k<n-rmargin;++k)
if (map[j][k]){
map[j][k]=0;
for (int l=1;l<num;++l)
if (!map[j+patx[l]][k+paty[l]]) {
flag = false;
break;
}
else
map[j+patx[l]][k+paty[l]]=0;
if (!flag) break;
pnum-=num;
if (!pnum) break;
}
if (!flag) break;
if (!pnum) break;
}
if (!flag) printf("No\n");
else printf("Yes\n");
}
return 0;
}
yyong119's solution
#include <iostream>
#include <queue>
using namespace std;
priority_queue <int, vector<int>, greater<int> > que;
long n, cost, temp;
int main() {
cin>>n;
for (int i = 0; i < n; i++) {
cin>>temp;
que.push(temp);
}
while (que.size() != 1) {
temp = que.top(); que.pop();
temp += que.top(); que.pop();
cost +=temp; que.push(temp);
}
cout<<cost;
}