合并果子倒过来,贪心策略的正确性嘛。。大约凭借直觉想一下,因为次数要不停的往后累加,所以越小的越早合并越好,这样对后面影响小。严格证明就是huffman tree了。话说类似的贪心策略好像还有srm536的1000pt,因为那个题要求最大的合并方法,所以越小的越靠前合并对后面的影响就越小。
这种题,先用stl爽一下!
# include <cstdio> # include <algorithm> # include <string> # include <cstring> # include <iostream> # include <queue> typedef long long ll; using namespace std; priority_queue<int,vector<int>,greater<int> > q; int main() { int n,t,i; ll ans = 0ll; scanf("%d",&n); for (i=0;i<n;++i) { scanf("%d",&t); q.push(t); } while (q.size()!=1) { int a = q.top(); q.pop(); int b = q.top(); q.pop(); ans += (a+b); q.push(a+b); } printf("%lld ",ans); return 0; }
当然像我这种弱b还要手写个堆锻炼一下代码能力啊。。
看下面 - -
# include <cstdio> # include <algorithm> # include <string> # include <cstring> # include <iostream> # include <queue> typedef long long ll; using namespace std; int heap[50000],len=0; void push(int k) { heap[++len] = k; int i = len; while (i!=1&&heap[i]<heap[i/2]) { swap(heap[i],heap[i/2]); i /= 2; } } int top() { return heap[1]; } void pop() { if (len == 1) len--; else { int i = 1,j; heap[1] = heap[len]; len--; while (i<=len) { if (i*2<=len&&(i*2+1)<=len) { if (heap[i*2]<heap[i*2+1]) j = i*2; else j = i*2+1; if (heap[i]>heap[j]) { swap(heap[i],heap[j]); i = j; continue; } } else if (i*2<=len&&heap[i]>heap[i*2]) { swap(heap[i],heap[i*2]); i *= 2; continue; } break; } } } int main() { int n,t,i; ll ans = 0ll; scanf("%d",&n); for (i=0;i<n;++i) { scanf("%d",&t); push(t); } while (len!=1) { int a = top(); pop(); int b = top(); pop(); ans += (a+b); push(a+b); } printf("%lld ",ans); return 0; }