Trace Iamge

Trace Iamge
Problem Statement

NOTE: There are images in the examples section of this problem statement that help describe the problem. Please view the problem statement in the HTML window to view them.
Given a picture composed entirely of horizontal and vertical line segments, calculate the minimum number of times you must lift your pen to trace every line segment in the picture exactly n times.
Each line segment will be of the form "<x1> <y1> <x2> <y2>" (quotes for clarity), representing a segment from (x1,y1) to (x2,y2). Segments may cross each other. Segments may also overlap, in which case you should count the overlapping region as appearing in the drawing only once. For example, say the drawing were composed of two lines: one from (6,4) to (9,4), and one from (8,4) to (14,4). Even though they overlap from (8,4) to (9,4), you should treat the drawing as if it were a single line from (6,4) to (14,4). You would not need to lift your pen at all to trace this drawing.
Definition

Class:
PenLift
Method:
numTimes
Parameters:
String[], int
Returns:
int
Method signature:
int numTimes(String[] segments, int n)
(be sure your method is public)


Notes
-
The pen starts on the paper at a location of your choice. This initial placement does not count toward the number of times that the pen needs to be lifted.
Constraints
-
segments will contain between 1 and 50 elements, inclusive.
-
Each element of segments will contain between 7 and 50 characters, inclusive.
-
Each element of segments will be in the format "<X1>_<Y1>_<X2>_<Y2>" (quotes for clarity). The underscore character represents exactly one space. The string will have no leading or trailing spaces.
-
<X1>, <Y1>, <X2>, and <Y2> will each be between -1000000 and 1000000, inclusive, with no unnecessary leading zeroes.
-
Each element of segments will represent a horizontal or vertical line segment. No line segment will reduce to a point.
-
n will be between 1 and 1000000, inclusive.
Examples
0)

{"-10 0 10 0","0 -10 0 10"}
1
Returns: 1
This picture looks like a plus sign centered at the origin. One way to trace this image is to start your pen at (-10,0), move right to (10,0), lift your pen and place it at (0,-10), and then move up to (0,10). There is no way to trace the picture without lifting your pen at all, so the method returns 1.
1)

{"-10 0 0 0","0 0 10 0","0 -10 0 0","0 0 0 10"}
1
Returns: 1
The picture is the same as the previous example, except that it has been described with four line segments instead of two. Therefore, the method still returns 1.
2)


{"-10 0 0 0","0 0 10 0","0 -10 0 0","0 0 0 10"}
4
Returns: 0
You are now required to trace each segment exactly 4 times. You can do so without lifting your pen at all. Start at (0,0). Move your pen left to (-10,0), then back right to (0,0), then left again to (-10,0), then right again to (0,0). You have now traced the first line segment 4 times. Repeat this process for the other three segments as well. Since no pen lifts were required, the method returns 0.
3)


{"0 0 1 0",   "2 0 4 0",   "5 0 8 0",   "9 0 13 0",
 "0 1 1 1",   "2 1 4 1",   "5 1 8 1",   "9 1 13 1",
 "0 0 0 1",   "1 0 1 1",   "2 0 2 1",   "3 0 3 1",
 "4 0 4 1",   "5 0 5 1",   "6 0 6 1",   "7 0 7 1",
 "8 0 8 1",   "9 0 9 1",   "10 0 10 1", "11 0 11 1",
 "12 0 12 1", "13 0 13 1"}
1
Returns: 6
The picture looks like this:
 
To trace the picture using the minimum number of pen lifts, refer to the following diagram:
 
Start by placing your pen at the yellow dot. Trace the yellow square. Now lift your pen and place it on the red dot. Move downward, tracing the vertical line segment, and then around the perimeter of the red rectangle. Lift your pen again and place it on the green dot. Trace the green lines using the same method as you did for the red lines. Lift your pen a third time, placing it on the magenta dot. Trace the magenta lines in a similar fashion. You will need to lift your pen three more times to trace each of the leftover white segments, for a grand total of 6 pen lifts.
4)


{"-2 6 -2 1",  "2 6 2 1",  "6 -2 1 -2",  "6 2 1 2",
 "-2 5 -2 -1", "2 5 2 -1", "5 -2 -1 -2", "5 2 -1 2",
 "-2 1 -2 -5", "2 1 2 -5", "1 -2 -5 -2", "1 2 -5 2",
 "-2 -1 -2 -6","2 -1 2 -6","-1 -2 -6 -2","-1 2 -6 2"}
5
Returns: 3
This is an example of overlap. Once all the segments are drawn, the picture looks like this:
 
You would need to lift your pen 3 times to trace every segment in this drawing exactly 5 times.
5)


{"-252927 -1000000 -252927 549481","628981 580961 -971965 580961",
"159038 -171934 159038 -420875","159038 923907 159038 418077",
"1000000 1000000 -909294 1000000","1000000 -420875 1000000 66849",
"1000000 -171934 628981 -171934","411096 66849 411096 -420875",
"-1000000 -420875 -396104 -420875","1000000 1000000 159038 1000000",
"411096 66849 411096 521448","-971965 580961 -909294 580961",
"159038 66849 159038 -1000000","-971965 1000000 725240 1000000",
"-396104 -420875 -396104 -171934","-909294 521448 628981 521448",
"-909294 1000000 -909294 -1000000","628981 1000000 -909294 1000000",
"628981 418077 -396104 418077","-971965 -420875 159038 -420875",
"1000000 -1000000 -396104 -1000000","-971965 66849 159038 66849",
"-909294 418077 1000000 418077","-909294 418077 411096 418077",
"725240 521448 725240 418077","-252927 -1000000 -1000000 -1000000",
"411096 549481 -1000000 549481","628981 -171934 628981 923907",
"-1000000 66849 -1000000 521448","-396104 66849 -396104 1000000",
"628981 -1000000 628981 521448","-971965 521448 -396104 521448",
"-1000000 418077 1000000 418077","-1000000 521448 -252927 521448",
"725240 -420875 725240 -1000000","-1000000 549481 -1000000 -420875",
"159038 521448 -396104 521448","-1000000 521448 -252927 521448",
"628981 580961 628981 549481","628981 -1000000 628981 521448",
"1000000 66849 1000000 -171934","-396104 66849 159038 66849",
"1000000 66849 -396104 66849","628981 1000000 628981 521448",
"-252927 923907 -252927 580961","1000000 549481 -971965 549481",
"-909294 66849 628981 66849","-252927 418077 628981 418077",
"159038 -171934 -909294 -171934","-252927 549481 159038 549481"}
824759
Returns: 19

 
This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.
  1  import  java.util.Iterator;
  2  import  java.util.StringTokenizer;
  3  import  java.util.TreeMap;
  4  import  java.util.TreeSet;
  5 
  6  /**
  7   *  @author  Nicky Qu
  8   * All Rights Reserved. Oct.25th,2007.
  9    */
 10  public   class  PenLift {
 11 
 12       private   int [] x1;
 13       private   int [] y1;
 14       private   int [] x2;
 15       private   int [] y2;
 16       private   int  cnt;
 17 
 18       public  PenLift() {
 19          x1  =   new   int [ 50 ];
 20          y1  =   new   int [ 50 ];
 21          x2  =   new   int [ 50 ];
 22          y2  =   new   int [ 50 ];
 23          cnt  =   0 ;
 24      }
 25 
 26       public   int  numTimes(String[] segments,  int  n) {
 27           for  ( int  i  =   0 ; i  <  segments.length; i ++ ) {
 28              compress();
 29          }
 30          constructGrid( 4 );
 31           int  r4  =  draw();
 32          constructGrid( 3 );
 33           int  r3  =  draw();
 34          constructGrid( 2 );
 35           int  r2  =  draw();
 36          constructGrid( 1 );
 37           int  r1  =  draw();
 38           if  (n  %   2   ==   0 ) {
 39               return  (r2  ==   24 ?  r2 : r2  *  (n  /   2 );
 40          }  else  {
 41               return  (r1  ==   23 ?  r1 : r2  *  (n  /   2 +  r1;
 42          }
 43      }
 44 
 45       public   void  addLine(String l) {
 46          StringTokenizer st  =   new  StringTokenizer(l,  "   " );
 47           int  _x1  =  Integer.parseInt(st.nextToken());
 48           int  _y1  =  Integer.parseInt(st.nextToken());
 49           int  _x2  =  Integer.parseInt(st.nextToken());
 50           int  _y2  =  Integer.parseInt(st.nextToken());
 51 
 52           if  (_x1  >  _x2) {
 53               int  tmp  =  _x1;
 54              _x1  =  _x2;
 55              _x2  =  tmp;
 56          }
 57           if  (_y1  >  _y2) {
 58               int  tmp  =  _y1;
 59              _y1  =  _y2;
 60              _y2  =  tmp;
 61          }
 62 
 63          x1[cnt]  =  _x1;
 64          y1[cnt]  =  _y1;
 65          x2[cnt]  =  _x2;
 66          y2[cnt]  =  _y2;
 67          cnt ++ ;
 68      }
 69 
 70       static  TreeMap < Integer, Integer >  collect( int [] a,  int [] b) {
 71          TreeSet < Integer >  set  =   new  TreeSet < Integer > ();
 72           for  ( int  i = 0 ; i  <  a.length; i ++ ) {
 73              set.add( new  Integer(a[i]));
 74          }
 75           for  ( int  i = 0 ; i  <  b.length; i ++ ) {
 76              set.add( new  Integer(b[i]));
 77          }
 78          TreeMap < Integer, Integer >  map  =   new  TreeMap < Integer, Integer > ();
 79           int  c  =   0 ;
 80           for  (Iterator < Integer >  it  =  set.iterator(); it.hasNext();) {
 81              map.put(it.next(),  new  Integer(c ++ ));
 82          }
 83           for  ( int  i  =   0 ; i  <  a.length; i ++ ) {
 84              a[i]  =  map.get( new  Integer(a[i])).intValue();
 85          }
 86           for  ( int  i  =   0 ; i  <  b.length; i ++ ) {
 87              b[i]  =  map.get( new  Integer(b[i])).intValue();
 88          }
 89           return  map;
 90      }
 91       int  sizex;
 92       int  sizey;
 93 
 94       public   void  compress() {
 95          TreeMap < Integer, Integer >  xmap  =  collect(x1, x2);
 96          TreeMap < Integer, Integer >  ymap  =  collect(y1, y2);
 97          sizex  =  xmap.size();
 98          sizey  =  ymap.size();
 99      }
100       private   int [][] gridH;
101       private   int [][] gridV;  // lines remaining from (x,y) to (x+1,y)/(x,y+1)
102 
103       public   void  constructGrid( int  n) {
104          gridH  =   new   int [sizex][sizey];
105          gridV  =   new   int [sizex][sizey];
106           for  ( int  i  =   0 ; i  <  cnt; i ++ ) {
107               if  (x1[i]  ==  x2[i]) {
108                   int  x  =  x1[i];
109                   for  ( int  y  =  y1[i]; y  <  y2[i]; y ++ ) {
110                      gridV[x][y]  =  n;
111                  }
112              }  else  {
113                   int  y  =  y1[i];
114                   for  ( int  x  =  x1[i]; x  <  x2[i]; x ++ ) {
115                      gridH[x][y]  =  n;
116                  }
117              }
118          }
119      }
120       private   int  posx;
121       private   int  posy;
122 
123       public   int  draw() {
124           int  res  =   0 ;
125           while  (findStart()) {
126               int  segs  =   0 ;
127              res ++ ;
128               boolean  OK;
129               do  {
130                  OK  =   false ;
131                   int  max  =  maxFrom(posx, posy);
132                  segs ++ ;
133                   if  (gridH[posx][posy]  ==  max) {
134                      gridH[posx][posy] -- ;
135                      posx ++ ;
136                      OK  =   true ;
137                       continue ;
138                  }
139                   if  (gridV[posx][posy]  ==  max) {
140                      gridV[posx][posy] -- ;
141                      posy ++ ;
142                      OK  =   true ;
143                       continue ;
144                  }
145                   if  (posx  >   0   &&  gridH[posx  -   1 ][posy]  ==  max) {
146                      gridH[posx  -   1 ][posy] -- ;
147                      posx -- ;
148                      OK  =   true ;
149                       continue ;
150                  }
151                   if  (posy  >   0   &&  gridV[posx][posy  -   1 ==  max) {
152                      gridV[posx][ - 1 ] -- ;
153                      posx -- ;
154                      OK  =   true ;
155                       continue ;
156                  }
157                   if  ( ! OK) {
158                      segs -- ;
159                  }
160              }  while  (OK);
161          }
162           if  (res  >   0 ) {
163              res -- ;
164          }
165           return  res;
166      }
167 
168       boolean  findStart() {
169           boolean  atAll  =   false ;
170           for  ( int  x  =   0 ; x  <  sizex; x ++ ) {
171               for  ( int  y  =   0 ; y  <  sizey; y ++ ) {
172                   if  (gridH[x][y]  >   0   ||  gridV[x][y]  >   0 ) {
173                       if  ( ! atAll) {
174                          atAll  =   true ;
175                          posx  =  x;
176                          posy  =  y;
177                      }
178                  }
179                   if  (count(x, y)  %   2   ==   1 ) {
180                      posx  =  x;
181                      posy  =  y;
182                       return   true ;
183                  }
184              }
185          }
186           return  atAll;
187      }
188 
189       public   int  maxFrom( int  x,  int  y) {
190           int  a1  =  gridH[x][y];
191           int  a2  =  gridV[x][y];
192           int  a3  =  x  >   0   ?  gridH[x  -   1 ][y] :  0 ;
193           int  a4  =  y  >   0   ?  gridV[x][y  -   1 ] :  0 ;
194           int  max  =   - 1 ;
195           if  (a1  >   0   &&  a1  >  max) {
196              max  =  a1;
197          }
198           if  (a2  >   0   &&  a2  >  max) {
199              max  =  a2;
200          }
201           if  (a3  >   0   &&  a3  >  max) {
202              max  =  a3;
203          }
204           if  (a4  >   0   &&  a4  >  max) {
205              max  =  a4;
206          }
207           return  max;
208      }
209 
210       public   int  count( int  x,  int  y) {
211           int  c1  =  (gridH[x][y]  >   0 ?   1  :  0 ;
212           int  c2  =  (gridV[x][y]  >   0 ?   1  :  0 ;
213           int  c3  =  (x  >   0   &&  gridH[x  -   1 ][y]  >   0 ?   1  :  0 ;
214           int  c4  =  (y  >   0   &&  gridH[x][y  -   1 >   0 ?   1  :  0 ;
215           return  c1  +  c2  +  c3  +  c4;
216      }
217  }

你可能感兴趣的:(Trace Iamge)