Stone Pile

Problem

  You have a number of stones with known weights w 1, …, wn. Write a program that will rearrange the stones into two piles such that weight difference between the piles is minimal.

 

Input

  Input contains the number of stones n (1 ≤ n ≤ 20) and weights of the stones w 1, …, wn (integers, 1 ≤ wi ≤ 100000) delimited by white spaces.
 

Output

  Your program should output a number representing the minimal possible weight difference between stone piles.
 

Example

inputoutput
5
5 8 13 27 14
3
 
 
  
题目大意
  给出一坨重量不定的石头,将其分成两份使得其重量差值最小。
 
题目解读
  石头总数很少,重量偏大(也不是十分大)。
 
算法
  设所有石头总重量为 S,要使两份石头重量差值最小,换句话说就是让每一份石头的重量都尽量接近 S / 2。
  考虑一个容量为 ⌈S / 2⌉ 的背包,用石头把这个背包尽量填满,此时将所有石头以是否在背包中为标准,分成两堆,这两堆石头重量差值即为题目所求解。
  直接套用 0-1 背包,f[i] = max{f[i - w[j]] + w[j]},时间复杂度 O(NS)。
 
代码
 1 n = int(input())
 2 w = input().split()
 3 for i in range(n):
 4     w[i] = int(w[i])
 5 s = sum(w)
 6 m = s - s // 2
 7 f = [0 for i in range(m + 1)]
 8 for i in range(n):
 9     for j in range(m, w[i] - 1, -1):
10         f[j] = max(f[j], f[j - w[i]] + w[i])
11 print(abs(s - f[m] * 2))

 

算法 2
  本来想用背包直接偷鸡,实际上上述算法也是足够快的,但无奈 Python 速度实在无法与 C++ 相比。
  老老实实改用搜索,时间复杂度 O(2N),保险起见排了个序加了个可行性剪枝。
 
代码 2
 1 n = int(input())
 2 w = input().split()
 3 
 4 def dfs(now, size):
 5     if ((now == n) or (size < w[now])):
 6         return size;
 7     return min(dfs(now + 1, size - w[now]), dfs(now + 1, size))
 8 
 9 
10 for i in range(n):
11     w[i] = int(w[i])
12 w.sort()
13 s = sum(w)
14 m = s - s // 2
15 print(abs(s - (m - dfs(0, m)) * 2))

 

代码解读

  注意:以下内容完全根据笔者自己对 Python 3 的理解胡说八道。

  sum():求和函数,返回列表所有元素的和。

  max():最大值函数,返回若干个数(或列表)中最大的元素。

  abs():绝对值函数,返回一个数的绝对值。

  def:定义函数(?)。

  min():最小值函数,返回若干个数(或列表)中最小的元素。

  sort():排序函数,默认将列表元素按升序排序。

posted @ 2018-03-17 02:10  Efve  阅读(380)  评论(0编辑  收藏  举报