ACM水题-合并果子(堆结构,贪心算法,AC)
来源:互联网 发布:四十而立五十而知天命 编辑:程序博客网 时间:2024/04/29 19:47
合并果子
Time Limit:1000MS Memory Limit:65536K
Total Submit:285 Accepted:112
Description
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。
Input
输入包括两行,第一行是一个整数n(1<=n<=10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i种果子的数目。
Output
输出包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于2^31。
Sample Input
3 1 2 9
Sample Output
15
Source
NOIP 2004
/*-----------------------------------------------------先排序,每次找最少数量的两堆合并。再排序,再找最少数量的两堆 。。。结果超时了。。。 -----------------------------正确应该是先建立一个最小堆,然后取出根,再重新整理堆,再取出来。。。取出根,整理堆这一个操作的时间复杂度为o(lgn),要取n-1次,所以总的时间复杂的度o(nlgn)。之前的想法错在,每一次取完之后,就再排序一次,排一次的平均时间为o(nlgn),n-1次,所以就变成了O(n^2lgn)。。大了足足一个数量级,所以肯定超时。这里没有注意到的是,在一个最小堆的基础是,取走根,然后重新整理堆这一个操作,时间只有和堆的高度有关。。。算法导论上面也有说 “总之,一个堆可以在O(lgn)时间内,支持大小为n的集合上的任意优先队列操作”~~~~~Orz~~~~ 状况:AC,15MS-----------------------------------------------------*/#include<stdio.h>#define PARENT(i) ((i)/2) #define LEFT(i) (2*(i))#define RIGHT(i) ((2*(i))+1)long a[10002] ;void MinHeapify(long i) ;long HeapExtractMin() ;void HeapInsert(long key) ;int main(void){long n = 0 ;long i = 0 ;long nTotal = 0 ;long nLength = 0 ;long nFir = 0 ;long nSec = 0 ;scanf("%ld",&n) ;for(i = 1 ; i <= n ; ++i){scanf("%ld",&a[i]) ;}a[0] = n ; nLength = a[0] ;for(i = nLength/2 ; i >= 1 ; --i){MinHeapify(i) ;}while(a[0] > 1){nFir = HeapExtractMin() ;nSec = HeapExtractMin() ; HeapInsert(nFir+nSec) ;nTotal += nFir+nSec ;}printf("%ld\n",nTotal) ;return 0 ;}void MinHeapify(long i) {long l = LEFT(i) ;long r = RIGHT(i) ;long lowest = 0 ;long temp = 0 ;do{ l = LEFT(i) ; r = RIGHT(i) ;if(l <= a[0] && a[l] < a[i]){lowest = l ;}else{lowest = i ;}if(r <= a[0] && a[r] < a[lowest]){lowest = r ;}if(i != lowest){temp = a[lowest] ;a[lowest] = a[i] ;a[i] = temp ;i = lowest ;lowest = 0 ;}}while(i != lowest) ;}long HeapExtractMin(){long nMin = a[1] ;long temp = 0 ;a[1] = a[a[0]] ; a[0]-- ;MinHeapify(1) ;return nMin ;}void HeapInsert(long key){long nTemp = 0 ;long i = 0 ;a[0]++ ;a[a[0]] = key ;while(i > 1 && a[PARENT(i)] > a[i]){nTemp = a[i] ;a[i] = a[PARENT(i)] ;a[PARENT(i)] = nTemp ;i = PARENT(i) ;}}
/*-----------------------------------------------------先排序,每次找最少数量的两堆合并。再排序,再找最少数量的两堆 。。。结果超时了。。。-----------------------------------------------------*/#include<stdio.h>#define PARENT(i) ((i)/2) #define LEFT(i) (2*(i))#define RIGHT(i) (2*(i)+1)long a[10004] ;long nHeapSize = 0 ;long nLength = 0 ;long nBegin = 2 ; void MaxHeapify(long i) ;void BuildMaxHeap() ;void HeapSort() ;int main(void){long n = 0 ;long i = 0 ;long nTotalStrenth = 0 ;long nTemp = 0 ;long nFruitSum = 0 ;scanf("%ld",&n) ;nLength = n ;for(i = 1 ; i <= n ; ++i){scanf("%ld",&a[i]) ;}HeapSort() ;for(i =1 ; i <= n-1 ; ++i){a[i+1] += a[i] ;nFruitSum = a[i+1] ; nTotalStrenth += nFruitSum ;a[i]= 0 ;if(i < n-2 && nFruitSum > a[i+2]){nBegin = i+1 ; HeapSort() ;}}if(1 == n)nTotalStrenth = a[1] ;printf("%ld\n",nTotalStrenth) ;return 0 ;}void MaxHeapify(long i) {long l = LEFT(i) ;long r = RIGHT(i) ;long largest = 0 ;long temp = 0 ;while(i != largest){if(l <= nHeapSize && a[l] > a[i]){largest = l ;}else{largest = i ;}if(r <= nHeapSize && a[r] > a[largest]){largest = r ;}if(i != largest){temp = a[largest] ;a[largest] = a[i] ;a[i] = temp ;MaxHeapify(largest) ;}}}void BuildMaxHeap(){nHeapSize = nLength ; long i = 0 ;for(i = nLength/2 ; i >= 1 ; --i){MaxHeapify(i) ;}}void HeapSort() {long i = 0 ;long nTemp = 0 ;BuildMaxHeap() ;for(i = nLength ; i >= nBegin ; --i){nTemp = a[1] ;a[1] = a[i] ;a[i] = nTemp ;nHeapSize-- ;MaxHeapify(1) ;}}
- ACM水题-合并果子(堆结构,贪心算法,AC)
- 合并果子_tyvj1066_vijos1097_codevs1063_贪心+堆
- 平衡堆+贪心 hdu1588 合并果子
- |Tyvj|NOIP2004|堆|贪心|P1066 合并果子
- luogu1090(堆,排序,贪心)合并果子
- ACM 75. [NOIP2004] 合并果子(水贪心)
- 贪心&合并果子
- codevs1063 合并果子 贪心
- 【堆排】合并果子
- 合并果子(堆)
- 数据结构----堆----合并果子
- 合并果子,浅谈堆
- 树-堆结构练习——合并果子之哈夫曼树
- 树-堆结构练习——合并果子之哈夫曼树
- 树-堆结构练习——合并果子之哈夫曼树
- 树-堆结构练习——合并果子之哈夫曼树
- 树-堆结构练习——合并果子之哈夫曼树
- 树-堆结构练习——合并果子之哈夫曼树
- zoomla!逐浪CMS分享php与.Net的比较
- 黑马程序员——集合框架(二)
- 浏览器对象模型
- uboot SPL Overview
- jquery学习
- ACM水题-合并果子(堆结构,贪心算法,AC)
- Qt Creator for PlayBook上的HelloWorld (Windows版)
- 新uboot的链接基址 -- CONFIG_SYS_TEXT_BASE
- mysql update语句 正则替换
- Java BorderFactory
- 商业分析——竞争(一)
- java编程基础1
- can1--can初探
- 杭电2014 青年歌手大奖赛_评委会打分