zoukankan      html  css  js  c++  java
  • 笨笨熊搬家打包篇

    描述:

      
    森林里的笨笨熊今天可开心啦——他买了新房子,乔迁新喜要搬家了。因此,笨笨熊请了许多好朋友来帮忙搬家,并准备了很多小纸盒用来装需要搬的物品,不过,这些纸盒的容积都是相同的,并且最多只能装两个物品。但是,为了不打扰太多的朋友,笨笨熊想了个“聪明”办法:让每个纸盒使用效率最高(注:只要纸盒容积大于物品的体积之和就认为可以装下物品体积不会大于纸盒容积),这样需要的纸盒最少。为了帮助笨笨熊提前通知朋友,请你根据笨笨熊的办法,帮忙算出:需要纸盒的最少数目是多少?        
    运行时间限制: 无限制 内存限制: 无限制 输入:  
    整数V——纸盒的容积; 整数N——物品的总数目N; 
    共N个整数(对应N个物品的体积,每个整数用空格隔开)。   
    输出:  
    整数M——需要纸盒的最少数目

    样例输入:
    10
    2
    2 3
    样例输出:
    1

     这里给出一种比较容易实现的解法:首先对所有物品的体积按从小到大进行排序,然后设计两个指针分别指向目前“未装箱”的容积最小和最大的物品,然后首先判断容积最大的物品是否小于盒子的容积,如果是,则判断加上最左边容积最小的物品后体积是否仍然小于盒子容积,如果仍然小,则left指针向右移动一个位置,继续判断,直到总和超过盒子容积停止,并将计数器加1,进入下一轮判断。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 //插入排序
     5 void insertion_sort(int a[], int n)
     6 {
     7     int i, j, t;
     8 
     9     for (i = 0; i < n-1; i++){
    10         for (j = i+1; j > 0; j--){
    11             if (a[j] < a[j-1]){
    12                 t = a[j];
    13                 a[j] = a[j-1];
    14                 a[j-1] = t;
    15             }else break;
    16         }
    17     }
    18 }
    19 
    20 //先排序,然后最大与最小相加
    21 int box_count(int volume[], int n, int box_size)
    22 {
    23     int left = 0, right = n-1, count = 0, total;
    24 
    25     insertion_sort(volume, n);
    26 
    27     while (left <= right){
    28         if (volume[right] <= box_size){
    29             total = volume[right];
    30             while (left < right && total + volume[left] <= box_size){
    31                 total += volume[left];
    32                 left++;
    33             }
    34             count++;
    35             right--;
    36         }
    37     }
    38 
    39     return count;
    40 }
    41 
    42 int main(void)
    43 {
    44     int i, box_size, num;
    45     int *list;
    46 
    47     scanf("%d", &box_size);//纸箱容积
    48     scanf("%d", &num);     //物品个数
    49 
    50     list = (int *)malloc(num * sizeof(int));
    51     //依次输入每个物品的体积
    52     for (i = 0; i < num; i++){
    53         scanf("%d", &list[i]);
    54     }
    55 
    56     printf("%d
    ", box_count(list, num, box_size));
    57 
    58     return 0;
    59 }

     但是,这种方法可能存在一些问题,因为到最后小的物品都装完了,可能导致剩下的每一件物品都需要占用一个盒子的情况。为此,我们切换一种思路:仍然首先对这些物品按照体积从小到大进行排序,然后从最大的物品开始查找,如果体积最大的物品未装箱(需要使用额外的空间来存储该物品是否已经装箱),就首先将其装入箱中,然后从体积次大的物品开始搜索,如果该物品未装箱并且能够继续装入箱中,则添加到此箱中,如果不过,再检查更小的物品,直到遍历至体积最小物品停止。

     1 //先排序,然后最大加上次大,依次寻找满足条件的组合
     2 int box_count2(int volume[], int n, int box_size)
     3 {
     4     int left = 0, right = n-1, count = 0, total;
     5     int* flag = (int *)calloc(n, sizeof(int));//用于标记对应元素是否已经装箱
     6 
     7     insertion_sort(volume, n);
     8 
     9     printf("Method 2#
    ");
    10     while (right >= 0){//从最大向最小寻找
    11         if (flag[right] == 0 && volume[right] <= box_size){
    12             printf("[ %d ", volume[right]);//输出满足条件的组合
    13 
    14             flag[right] = 1;//将此物品装箱
    15             total = volume[right];
    16             left  = right - 1;
    17             while (left >= 0){
    18                 //如果左侧物品未装箱并且可以继续加入本箱中
    19                 if (flag[left] == 0 && total + volume[left] <= box_size){
    20                     printf("%d ", volume[left]);//输出满足条件的组合
    21 
    22                     flag[left] = 1;//将此物品装箱
    23                     total += volume[left];
    24                 }
    25                 left--;
    26             }
    27 
    28             //装满一箱
    29             printf("]
    ");
    30             count++;
    31         }
    32         right--;
    33     }
    34 
    35     return count;
    36 }

    然后,我们可以重新写一个测试程序,输出两种方法的装箱结果,完整代码如下:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 //插入排序
      5 void insertion_sort(int a[], int n)
      6 {
      7     int i, j, t;
      8 
      9     for (i = 0; i < n-1; i++){
     10         for (j = i+1; j > 0; j--){
     11             if (a[j] < a[j-1]){
     12                 t = a[j];
     13                 a[j] = a[j-1];
     14                 a[j-1] = t;
     15             }else break;
     16         }
     17     }
     18 }
     19 
     20 //先排序,然后最大与最小相加
     21 int box_count(int volume[], int n, int box_size)
     22 {
     23     int left = 0, right = n-1, count = 0, total;
     24 
     25     insertion_sort(volume, n);
     26 
     27     printf("Method 1#
    ");
     28     while (left <= right){
     29         if (volume[right] <= box_size){
     30             printf("[ %d ", volume[right]);//输出满足条件的组合
     31             total = volume[right];
     32             while (left < right && total + volume[left] <= box_size){
     33                 printf("%d ", volume[left]);
     34                 total += volume[left];
     35                 left++;
     36             }
     37             printf("]
    ");
     38             count++;
     39             right--;
     40         }
     41     }
     42 
     43     return count;
     44 }
     45 
     46 //先排序,然后最大加上次大,依次寻找满足条件的组合
     47 int box_count2(int volume[], int n, int box_size)
     48 {
     49     int left = 0, right = n-1, count = 0, total;
     50     int* flag = (int *)calloc(n, sizeof(int));//用于标记对应元素是否已经装箱
     51 
     52     insertion_sort(volume, n);
     53 
     54     printf("Method 2#
    ");
     55     while (right >= 0){//从最大向最小寻找
     56         if (flag[right] == 0 && volume[right] <= box_size){
     57             printf("[ %d ", volume[right]);//输出满足条件的组合
     58 
     59             flag[right] = 1;//将此物品装箱
     60             total = volume[right];
     61             left  = right - 1;
     62             while (left >= 0){
     63                 //如果左侧物品未装箱并且可以继续加入本箱中
     64                 if (flag[left] == 0 && total + volume[left] <= box_size){
     65                     printf("%d  ", volume[left]);//输出满足条件的组合
     66 
     67                     flag[left] = 1;//将此物品装箱
     68                     total += volume[left];
     69                 }
     70                 left--;
     71             }
     72 
     73             //装满一箱
     74             printf("]
    ");
     75             count++;
     76         }
     77         right--;
     78     }
     79 
     80     return count;
     81 }
     82 
     83 
     84 int main(void)
     85 {
     86     int i, box_size, num;
     87     int *list;
     88 
     89     scanf("%d", &box_size);//纸箱容积
     90     scanf("%d", &num);     //物品个数
     91 
     92     list = (int *)malloc(num * sizeof(int));
     93     //依次输入每个物品的体积
     94     for (i = 0; i < num; i++){
     95         scanf("%d", &list[i]);
     96     }
     97 
     98     printf("%d
    ", box_count(list, num, box_size));
     99     printf("%d
    ", box_count2(list, num, box_size));
    100 
    101     printf("Done.
    ");
    102     return 0;
    103 }
    View Code

    为了测试这两种算法的差异,我们输入的物品体积尽量比箱子容量的一半大一点,本次测试用的数据如下:

    运行程序,输出结果如下:

    从这个测试结果来看,两种算法输出的箱子总数还是相同的,只不过组合不同,第二种方法能够按照total从大到小的顺序输出结果,而第一种方法没有规律可言。

    有没有人能够找出一组数据使得两种方法输出结果不同呢?

  • 相关阅读:
    学生管理系统初步总结
    ListView控件详解
    Windows窗体应用布局详解
    winforms控件
    指尖上的数据库之探囊取物
    指尖上的数据库之无中生有
    银行bank系统项目实践
    QT Creator 快速入门教程 读书笔记(一)
    我的程序员之路(英语的学习)
    游戏开发完整学习路线(各个版本都有)
  • 原文地址:https://www.cnblogs.com/xiaomanon/p/4468147.html
Copyright © 2011-2022 走看看