银河

SKYIV STUDIO

  博客园 :: 首页 :: 博问 :: 闪存 :: :: :: 订阅 订阅 :: 管理 ::
Timus 1005. Stone pile 要求将若干石头分为两堆使其重量差最小。

1005. Stone pile

Time Limit: 2.0 second
Memory Limit: 16 MB

You have a number of stones with known weights W1, …, 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 W1, …, Wn (1 ≤ Wi ≤ 100000) delimited by white spaces.

Output

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

Sample

inputoutput
5
5
8
13
27
14
3
Problem Source: USU Championship 1997

解答如下:

 1 using System;
 2 using System.IO;
 3 using System.Text.RegularExpressions;
 4 
 5 // http://acm.timus.ru/problem.aspx?space=1&num=1005
 6 class Acm1005
 7 {
 8   static void Main()
 9   {
10     new Acm1005().Run(Console.In, Console.Out);
11   }
12 
13   void Run(TextReader reader, TextWriter writer)
14   {
15     writer.WriteLine(GetResult(GetWeigths(reader)));
16   }
17 
18   int[] GetWeigths(TextReader reader)
19   {
20     string[] ss = Regex.Split(reader.ReadToEnd().Trim(), @"\s+");
21     int[] weigths = new int[int.Parse(ss[0])];
22     for (int i = 0; i < weigths.Length; i++) weigths[i] = int.Parse(ss[i + 1]);
23     return weigths;
24   }
25 
26   int GetResult(int[] weigths)
27   {
28     int n = weigths.Length - 1;
29     int result = int.MaxValue;
30     int[] piles = new int[2];
31     for (int i = (1 << n) - 1; i >= 0; i--)
32     {
33       piles[0= weigths[n];
34       piles[1= 0;
35       for (int j = n - 1; j >= 0; j--) piles[(((i >> j) & 1== 0? 1 : 0+= weigths[j];
36       int v = Math.Abs(piles[0- piles[1]);
37       if (result > v) result = v;
38     }
39     return result;
40   }
41 }

这道题是说,给你一堆石头,总数在 1 到 20 之间,每个石头的重量在 1 到 100,000 之间。要求你将这堆石头分成两堆,使这两堆石头的重量差最小,并输出这个重量差。

由于这道题目的时间限制是 2.0 秒(这个时间非常宽松了),且输入的规模不大(石头的总数不超过 20),所以我是用蛮力搜索穷举每一种可能的分配方案,找出最优的。

程序中第 26 到 40 行的 GetResult 方法的输入参数 weigths 数组记录每个石头的重量。第 29 行 result 变量就是用来记录两堆石头的重量差的,也就是我们要输出的结果。第 30 行 int 类型数组 piles 的长度为 2,它的两个元素分别代表两堆石头的重量。

程序中第 28 行将 n 设为石头总数减一,这有两重含义:首先,在第 33 行将第 n 个(也是最后一个,因为 C# 数组的下标是从 0 开始的)石头分配到第 0 堆(piles[0])中。其次,蛮力搜索需要穷举 2n 种可能的情况,这体现在第 31 行开始的循环中,变量 i 从 2n -1 开始递减到 0 以遍历这 2n 种可能的情况。

程序中第 35 行的循环根据变量 i 的值(该值代表了蛮力搜索的每一种可能的分配方案)将石头分配到两堆中,这是根据 i 的第 j 位是否为 0 来决定的,如果为 0 则分配到第 1 堆中,否则就分配到第 0 堆中。第 36 行计算这两堆石头的重量差,第 37 行用来更新最小的重量差。

这个算法仅仅是能够 Accepted 而已(这个程序的实际运行时间是 0.171 秒,没有超过 2.0 秒的时间限制),她的优点是简单明了,但该算法肯定不是最优的。如果将问题的规模扩大,或者时间限制要求更严格的话,就需要寻找更好的算法了。

 

posted on 2008-07-26 10:04  银河  阅读(4159)  评论(5编辑  收藏  举报