本文出自:http://blog.csdn.net/svitter
题意:给你几根木板,让你连接起来,每次连接花费为两根长度之和。连接所有的木板,最后最小的花费是多少。
这个题目用贪心即可。即,每次的取两根最小的,花费最少,最后花费就最少。
本题目可以用二叉堆的最关键就在于二叉堆的定义:
大根堆:上面的比下面的大;
小根堆:上面的比下面的小;
通过一维数组最后一个添加或者删除,进行调整。
1.一般堆解法:
时间消耗:
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; __int64 a[20010]; int m, n; void heap(int m) { int t; while(m * 2 <= n)//有子堆 { m = m * 2; if(m < n && a[m] > a[m+1]) // 较大的子堆 { m++; } if(a[m] < a[m / 2]) // { t = a[m]; a[m] = a[m/2]; a[m/2] = t; } else break; } } void push_heap() { int i = n; __int64 x = a[n]; while(i > 1 && a[i/2] > x) { a[i] = a[i/2]; i /= 2; } a[i] = x; } void pop_heap() { __int64 x; //swap top.root x = a[1]; a[1] = a[n]; a[n] = x; n--; heap(1); } void make_heap() { int i; for(i = n / 2; i > 0; i --)//从n/2构建即可 { heap(i); } } void ace() { int i; __int64 cur0, cur1, cur, sum; while(~scanf("%d", &n)) { for(i = 1; i <= n; i++) { scanf("%I64d", &a[i]); } make_heap(); sum = 0; while(n != 1) { pop_heap(); cur0 = a[n+1]; pop_heap(); cur1 = a[n+1]; cur = cur0 + cur1; sum += cur; a[++n] = cur; push_heap(); } printf("%I64d\n", sum); } } int main() { ace(); return 0; }
时间消耗:
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; __int64 a[20010]; int m, n; void ace() { int i; __int64 cur0, cur1, cur, sum; while(~scanf("%d", &n)) { for(i = 1; i <= n; i++) { scanf("%I64d", &a[i]); } make_heap(); sum = 0; while(n != 1) { pop_heap(); cur0 = a[n+1]; pop_heap(); cur1 = a[n+1]; cur = cur0 + cur1; sum += cur; a[++n] = cur; push_heap(); } printf("%I64d\n", sum); } } int main() { ace(); return 0; }3.模板STL解法
没有写出来,方法就几个, 没有获取弹出堆首元素的方法。如果你会的话,请告诉我= =
POJ3253 Fence Repair (二叉堆),布布扣,bubuko.com
原文:http://blog.csdn.net/svitter/article/details/24554285