厦门理工oj 1270药不能停(C语言自己模拟堆)

药不能停

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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值