Journal Second

  • Journal Second

合并果子

​ Intro : 小学期没有上的程序设计与实践课重修开课了。每周三道题kkkk。

​ 合并果子感觉是个经典题目是吧。

在这里插入图片描述
刚看完简直是没有思路。然后各种搜索,知道了**堆(heap)优先队列(priority Queue)**的概念。

反正抛开一切,整体的思路大概是:每次都要取出质量最小的两堆合并,到最后所得到的耗费就是最少的

奈何不会用啊,数据结构真的会的很少qaq。

然后看见了一个大佬的不需要数据结构相关知识。然后有了一个比较简洁明了的流程:即对第一次的输入进入数组,进行排序。第一次先取出前两个元素相加,并把第二个元素加到第一个元素上来表示当前堆。之后进行覆盖操作。覆盖之后重点来了,此时对于数组中的各个元素,不要进行排序了,否则时间复杂度会很高。只需要用线性的方法,把此时数组的第一个元素放到正确位置即可(因为余下的元素都是已经排好顺序的)。重复直到数组中只剩下一个元素,输出结果即可。

下面走一下代码:

// 合并果子.cpp : 贪心算法。GCC4.8
//Ste-Made

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>
#include<math.h>

#define SIZE 10010
int heap_num;
int heap_weight[SIZE];
int sum = 0;

void Input(void);
void Output(int res);
void Sort(int* a, int num);//仅用于第一次排序



int main()
{
    int ans=0;
    int temp;
    Input();
    Sort(heap_weight, heap_num);
    //检验排序
   /* for (int i = 0; i < heap_num; i++)
        printf("%d ", heap_weight[i]);
    putchar('\n');*/
    while (heap_num > 1)
    {
        int first2 ;
        first2 = heap_weight[0] + heap_weight[1];
        sum += first2;//先取出前两个最小的相加一次
        heap_weight[1] += heap_weight[0];//把第一个元素的值加在第二个元素上以实现记录此次操作后的花费力气
        for (int i = 0; i < heap_num-1 ; i++)//进行覆盖(删除)操作
        {
            heap_weight[i] = heap_weight[i + 1];
        }
        heap_num--;
      /* putchar('\n');
        for (int i = 0; i < heap_num; i++)
            printf("%d ", heap_weight[i]);
        putchar('\n');*/
        //此时数组的第一个值为新出现的相加值
        for (int i = 0; i < heap_num-1; i++)//冒一次泡来将搬运后的值放置到正确位置
        {
            if (heap_weight[i] < heap_weight[i+1])
                continue;
            else
            {
                temp = heap_weight[i];
                heap_weight[i] = heap_weight[i + 1];
                heap_weight[i + 1] = temp;
            }
       }
        //检验当前值和排序后的结果
       //putchar('\n');
     /*   for (int i = 0; i < heap_num; i++)
            printf("%d ", heap_weight[i]); 
        putchar('\n');
        printf("Now sum :%d\n",sum);*/

    }
    ans = sum;

    Output(ans);
    return 0;
}

void Input(void) {

    scanf("%d", &heap_num);
    for (int i = 0; i < heap_num; i++)
    {
        scanf("%d", &heap_weight[i]);
    }
}

void Output(int res)
{
    printf("%d\n", res);
}

void Sort(int* a, int len)//Bubble sort
{
    int temp;
    for (int i = len-1; i ; i--)
    {
        for (int j = 0; j < i; j++)
        {
            if (a[j] < a[j + 1])
                ;
            else
            {
                temp = a[j + 1];
                a[j + 1] = a[j];
                a[j] = temp;
            }
        }
    }
}


其中排序就选择了比较简单的冒泡排序,毕竟只排一次。

然后用线性的方法把合并后的堆放到正确位置还是用了冒泡的思想吧》(我不确定诶,可能是?)

哦对了,当时遇到的一个问题,也是写了很多检验性代码的原因,就是在线性算法中,for循环边界值找错了,应该是heap_num-1而不是heap_num,然后就觉得,这方面真的要注意呀,就是循环的停止条件,尤其是涉及到数组。一些莫名其妙的bug应该就是从这儿来的。

哦对了,当时遇到的一个问题,也是写了很多检验性代码的原因,就是在线性算法中,for循环边界值找错了,应该是heap_num-1而不是heap_num,然后就觉得,这方面真的要注意呀,就是循环的停止条件,尤其是涉及到数组。一些莫名其妙的bug应该就是从这儿来的。

先这样吧嘻嘻,反正最后AC了还是蛮高兴的吖~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值