TopCoder: SRM579 DIV2 1000

Problem Statement

     NOTE: This problem statement contains images that may not display properly if viewed outside of the applet.



Everybody loves geometry, so here is a geometry problem. You have a few marbles of possibly different sizes. You are given a vector <int> radius that describes the marbles: each element of radius is the radius of one of your marbles.



You want to place all marbles onto a straight line that is drawn on the table. Clearly, this makes the problem two-dimensional: we can just view the marbles as circles that will all be touching the line from above. Of course, the marbles cannot overlap, so in our problem no two circles are allowed to overlap. Note that you may place the marbles onto the line in any order, you do not have to preserve the order in which they are given in radius.



Additionally, you want to pack the bottoms of the marbles as close together as possible. More precisely: For each marble consider the point where it touches the line. Compute and return the smallest possible distance between the farthest two of those points. (That is, if you imagine the line as going from the left to the right, your task is to minimize the distance between the leftmost and the rightmost of the points where the circles touch the line.)

Definition

    
Class: MarblePositioning
Method: totalWidth
Parameters: vector <int>
Returns: double
Method signature: double totalWidth(vector <int> radius)
(be sure your method is public)
    
 

Notes

- The returned values must have an absolute or relative error less than 1e-9.

Constraints

- radius will contain between 2 and 8 elements, inclusive.
- Each element of radius will be between 1 and 1000000000 (10^9), inclusive.

Examples

0)  
    
{1, 2}
Returns: 2.8284271247461903
One of the best ways to place the marbles is the following one:

TopCoder: SRM579 DIV2 1000
1)  
    
{7,7,7}
Returns: 28.0
 
2)  
    
{10, 20, 30}
Returns: 62.92528739883945
TopCoder: SRM579 DIV2 1000
3)  
    
{100, 100,11,11,25}
Returns: 200.0
TopCoder: SRM579 DIV2 1000
4)  
    
{1,999950884,1}
Returns: 63246.0
 

这题一开始是想自己将小圆塞入大圆与水平线的空隙之内,可是后来因为编程的难度再看了看题目的例子,发现并不需要塞入空隙,大圆间放小圆也能缩短间距。到最后我决定采用暴力DFS的方法,将所有可能的排列圆的方式计算间距,最后得到最短距离。

这里要指出的是在已经排好的圆集合后加上一个圆,新的距离不能只能单单计算已经排好的最右边的圆与新添加的圆的距离,因为可能与其他圆会有重叠。所以必须跟以前所有的圆都算距离,取最大值。具体代码如下

 1 // BEGIN CUT HERE

 2 

 3 // END CUT HERE

 4 #include <functional>

 5 #include <algorithm>

 6 #include <stdexcept>

 7 #include <iostream>

 8 #include <sstream>

 9 #include <fstream>

10 #include <iomanip>

11 #include <cstdlib>

12 #include <cstring>

13 #include <utility>

14 #include <cctype>

15 #include <vector>

16 #include <string>

17 #include <bitset>

18 #include <queue>

19 #include <stack>

20 #include <ctime>

21 #include <list>

22 #include <map>

23 #include <set>

24 #include <math.h>

25 

26 using namespace std;

27 

28 #define ll long long

29 #define MOD 1000000007

30 #define emin 1e-6

31 struct marble {

32     double pos;

33     double r;

34     marble(double a, double b) : pos(a), r(b) { }

35 };

36 

37 class MarblePositioning

38 {

39         public:

40 

41         double dis(double r, double R) {

42             return sqrt((r+R)*(r+R) - (r-R)*(r-R));

43         }

44         void dfs(double &ret, vector<int> &radius, vector<marble> &permutation, int dep, vector<bool> &visit) {

45             if (dep == radius.size()) {

46                 ret = min(ret, permutation[permutation.size()-1].pos - permutation[0].pos);

47                 return;

48             }

49 

50             for (int i = 0; i < radius.size(); i++) {

51                 if (!visit[i]) {

52                     marble tmp(0, double(radius[i]));

53                     double position = 0.0;

54                     if (permutation.size() == 0) position = 0.0;

55                     else for (int j = 0; j < permutation.size(); j++)

56                         position = max(position, permutation[j].pos+dis(permutation[j].r, radius[i]));

57                     tmp.pos = position;

58                     permutation.push_back(tmp);

59                     visit[i] = true;

60                     dfs(ret, radius, permutation, dep+1, visit);

61                     visit[i] = false;

62                     permutation.pop_back();

63                 }

64             }

65         }

66 

67         double totalWidth(vector <int> radius)

68         {

69             double ret = 1e13;

70             vector<bool> visit(radius.size(), false);

71             vector<marble> permutation;

72             dfs(ret, radius, permutation, 0, visit);

73             return ret;

74         }

75 

76 // BEGIN CUT HERE

77     public:

78     void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); }

79     private:

80     template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }

81     void verify_case(int Case, const double &Expected, const double &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }

82     void test_case_0() { int Arr0[] = {1, 2}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); double Arg1 = 2.8284271247461903; verify_case(0, Arg1, totalWidth(Arg0)); }

83     void test_case_1() { int Arr0[] = {7,7,7}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); double Arg1 = 28.0; verify_case(1, Arg1, totalWidth(Arg0)); }

84     void test_case_2() { int Arr0[] = {10, 20, 30}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); double Arg1 = 62.92528739883945; verify_case(2, Arg1, totalWidth(Arg0)); }

85     void test_case_3() { int Arr0[] = {100, 100,11,11,25}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); double Arg1 = 200.0; verify_case(3, Arg1, totalWidth(Arg0)); }

86     void test_case_4() { int Arr0[] = {1,999950884,1}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); double Arg1 = 63246.0; verify_case(4, Arg1, totalWidth(Arg0)); }

87 

88 // END CUT HERE

89 

90 };

91 // BEGIN CUT HERE

92 int main()

93 {

94         MarblePositioning ___test;

95         ___test.run_test(-1);

96         return 0;

97 }

98 // END CUT HERE

 

你可能感兴趣的:(topcoder)