zoukankan      html  css  js  c++  java
  • checkio——batteriesloading

      CheckiO上面的一道题目 Batteries Loading

      这倒题目的意思就是,给出一堆电池,每个电池有不同的重量,电池装在两只手上,怎样装载,才能使两只手上的电池重量之差最小,给出了一些例程:

    checkio([10,10]) == 0
    checkio([10]) == 10
    checkio([5, 8, 13, 27, 14]) == 3
    checkio([5,5,6,5]) == 1
    checkio([12, 30, 30, 32, 42, 49]) == 9
    checkio([1, 1, 1, 3]) == 0

      这道题很明显是动态规划问题,但我对动态规划并不是很熟悉,于是看了一阵时间的背包问题。

      事实上,这道题可以转化为背包问题,即,要使两只手臂装载的电池重量差最小,那应该让每只手臂越接近总重量的一半,才能使其差最小。

      在此,背包的容量就是总重量sum的一半,即halfsum,将所给的电池装入一个背包容量为halfsum的背包中,怎样装,能使箱子的重量达到最大?

      所以,首要问题,即找到最优子结构

      问题是当前阶段的剩余空间最小,并不意味下一阶段的剩余空间也一定最小,即该问题并不具备最优子结构的特征。但如果将装背包的体积作为状态的话,则阶段间的状态转移关系顺其自然,可使得最优化问题变为判定性问题。设状态转移方程

        f[i,j]——在前i个物品中选择若干个物品(必须包括物品i)装箱,其体积正好为j的标志。显然f[i,j]=f[i-1,j-box[i]],即物品i装入箱子后的体积正好为j的前提是f[i-1,j-box[i]]=true。初始时,f[0,0]=true(1≤i≤n,box[i]≤j≤halfsum)。

      我首先用C++代码实现,因为现在对C++较为熟悉:

     1 #include <iostream>
     2 #include <stdlib.h>
     3 #include <cstring>
     4 
     5 #define maxlength 100
     6 
     7 using namespace std;
     8 
     9 int things[maxlength];
    10 
    11 int main()
    12 {
    13     cout << "Hello World!" << endl;
    14     int in = 0;
    15     int n;
    16 
    17     while(cin >> n && cin.good())
    18     {
    19         things[in] = n;
    20         in++;
    21     }
    22 
    23     int sum = 0;
    24 
    25     if(in == 1)
    26     {
    27         cout << "Min minus is " << things[0] << endl;
    28 
    29         return 0;
    30     }
    31 
    32     for(int i = 0; i < in; i++)
    33     {
    34         sum += things[i];
    35     }
    36 
    37     /* 取总数值的一半作为背包的容量
    38      */
    39     int halfsum = sum/2;
    40 
    41     int* f0 = (int* )malloc((halfsum + 1) * sizeof(int));
    42     int* f1 = (int* )malloc((halfsum + 1) * sizeof(int));
    43 
    44     memset(f0, 0, (halfsum + 1)*sizeof(int));
    45     memset(f1, 0, (halfsum + 1)*sizeof(int));
    46 
    47     f0[0] = 1;
    48 
    49     /*
    50      *装入背包, f0记录i-1时刻背包的状态
    51      *f1记录i时刻背包的状态
    52      *f0[j]表示当前容量为j的背包恰好装满时,其值为1,否则为0, 同理f1[j]
    53      *初始状态,只有f0[0]为1
    54      *对于第i个物品,当f0[j-things[i]] = 1时,说明装入i物品,能使背包恰好装满,即f1[j] = 1, 即当前状态更新
    55      */
    56     for(int i = 0;i < in;i++)
    57     {
    58         for(int j = things[i];j <= halfsum; j++)
    59         {
    60             if(f0[j-things[i]])
    61             {
    62                 f1[j] = 1;
    63             }
    64         }
    65         for(int k = 1;k <= halfsum; k++)
    66         {
    67             f0[k]=f1[k];
    68         }
    69     }
    70 
    71     int k = halfsum;
    72     while(!f0[k])
    73     {
    74         k--;
    75     }
    76 
    77     /*
    78      *因为有两只背包,当其中一直装了k个时, 另一个有sum-k个
    79      *则差为 sum-k-k
    80      */
    81     int minminus = sum - 2*k;
    82 
    83     cout << "Min minus is " << minminus << endl;
    84 
    85     return 0;
    86 }

      其次转化为python的代码,这里碰到一个小问题,对于python而言, 如果令halfsum = sum/2的话,python会自动将halfsum默认设置为float型,所以需要前面加个int转换一下:

     1 def checkio(stones):
     2     '''
     3     minimal possible weight difference between stone piles
     4     '''
     5     slen = len(stones)
     6      
     7     if slen == 1 :
     8         return stones[0]
     9      
    10     sum = 0
    11     for i in stones :
    12         sum = sum + i
    13      
    14     halfsum = int(sum/2)
    15      
    16     f0 = [0] * (halfsum + 1)
    17     f1 = [0] * (halfsum + 1)
    18      
    19     f0[0] = 1
    20      
    21     for i in stones :
    22         for j in range(i, halfsum+1) :
    23             if f0[j-i] :
    24                 f1[j] = 1
    25         for k in range(1,  halfsum+1) :
    26             f0[k] = f1[k]
    27      
    28     k = halfsum
    29     while f0[k] == 0:
    30         k = k-1
    31      
    32     minminus = sum - 2*k
    33      
    34     return minminus
    35      
    36  
    37 if __name__ == '__main__':
    38     assert checkio([10,10]) == 0, 'First, with equal weights'
    39     assert checkio([10]) == 10, 'Second, with a single stone'
    40     assert checkio([5, 8, 13, 27, 14]) == 3, 'Third'
    41     assert checkio([5,5,6,5]) == 1, 'Fourth'
    42     assert checkio([12, 30, 30, 32, 42, 49]) == 9, 'Fifth'
    43     assert checkio([1, 1, 1, 3]) == 0, "Six, don't forget - you can hold different quantity of parts"
    44     print ('All is ok')

      当然,此题也有暴力解法,即用python的函数,求得输入序列的全排列,然后枚举每一个组合的差值,最后从其中选出最小值。

      

  • 相关阅读:
    实验四: Android程序设计
    实验三 敏捷开发与XP实践-1
    mini dc课堂练习补交
    20155216 2016-2017-2 《Java程序设计》第十周学习总结
    第十二周课上练习
    20155210 潘滢昊 Java第三次实验
    20155210 2016-2017-2 《Java程序设计》第10周学习总结
    20155210 潘滢昊2016-2017-2 《Java程序设计》第9周学习总结
    20155210潘滢昊 Java第二次试验
    20155210潘滢昊 2016-2017-2 《Java程序设计》第8周学习总结
  • 原文地址:https://www.cnblogs.com/moondark/p/2951908.html
Copyright © 2011-2022 走看看