药不能停
Time Limit:1000MS Memory Limit:65536K
Total Submit:1091 Accepted:251
Description
小明很喜欢算法和编程,他的大学学业生涯规划是:厦门理工学院程序设计大赛一等奖、福建省程序设计大赛金牌、蓝桥杯软件大赛全国一等奖、亚洲区域赛金牌、World final金牌、Google就业年薪百万。小明是懒癌晚期,他不想通过努力训练完成规划,他想通过吃药来提高智商,秒杀一众高手。
小明发现单吃一种药效果太差,他要将已有的N种药物混合成1种药再吃。已知每种药都有一定的毒性,将任意两种药混合的毒性为这两种药的毒性之和,混合产生的新药的毒性也同样为两种药的毒性之和。由于技术限制,小明每次只能挑选两种药进行混合。现在小明想知道将N种药合成1种药的最小毒性和。
Input
输入第一行为一个正整数N(1 <= N <= 100000)
接下来一行输入N个正整数,第i个整数a[i]代表第i种药的毒性( 1 <= a[i] <= 1000)
Output
输出一行一个整数,代表药的最小毒性和。
Sample Input
5
1 2 3 4 5
Sample Output
33
思路:小顶堆(优先队列),取两个最小的值然后求和并将求得的和加进总和,然后将两数的和放回堆里面去
//堆
#include<stdio.h>
int capacity;
int count;
int nums[100001];
void swap(int i,int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
void Heap(int numbers[],int len) {
int i;
capacity = len;
count = len;
for(i=0; i<len; i++) {
nums[i+1] = numbers[i];
}
}
void shiftUp(int count) {
while(count>1 && nums[count/2]>nums[count]){
swap(count,count/2);
count /= 2;
}
}
void insert(int num) {
nums[count+1] = num;
count++;
shiftUp(count);
}
void shiftDown(int k) {
int j;
while( 2* k<= count) {
j = 2*k;
if(j+1<=count && nums[j+1]<nums[j]){j++;}
if(nums[k] <= nums[j]){break;}
swap(j,k);
k = j;
}
}
void heapify() {
int i;
for(i=count/2; i>=1; i--) {
shiftDown(i);
}
}
int size(){return count;}
int isEmpty() {return count==0;}
int extraMin() {
int ret = nums[1];
swap(count,1);
count--;
shiftDown(1);
return ret;
}
void main() {
int n,i;
int numbers[100000];
int t;
int sum=0;
int tmp;
scanf("%d",&n);
t=n-1;
for(i=0; i<n; i++) {scanf("%d",&numbers[i]);}
Heap(numbers,n);
heapify();
while(t--) {
tmp = (extraMin() + extraMin());
sum += tmp;
insert(tmp);
}
printf("%d\n",sum);
}