有一种代码令人神往

  偶然看到Petr的AC代码,真的惊呆了,终于知道自己弱在哪里了,终于找到喜欢的风格了。

  1 import java.util.List;
  2 import java.io.IOException;
  3 import java.io.InputStreamReader;
  4 import java.util.Arrays;
  5 import java.util.ArrayList;
  6 import java.io.BufferedReader;
  7 import java.util.Comparator;
  8 import java.io.OutputStream;
  9 import java.io.PrintWriter;
 10 import java.util.Random;
 11 import java.util.StringTokenizer;
 12 import java.util.Collections;
 13 import java.io.InputStream;
 14 
 15 /**
 16  * Built using CHelper plug-in
 17  * Actual solution is at the top
 18  */
 19 public class Main {
 20     public static void main(String[] args) {
 21         InputStream inputStream = System.in;
 22         OutputStream outputStream = System.out;
 23         InputReader in = new InputReader(inputStream);
 24         PrintWriter out = new PrintWriter(outputStream);
 25         TaskE solver = new TaskE();
 26         solver.solve(1, in, out);
 27         out.close();
 28     }
 29 }
 30 
 31 class TaskE {
 32     static class Obstacle {
 33         int x;
 34         int y;
 35     }
 36 
 37     static class SumThenDiffComparator implements Comparator<Obstacle> {
 38         static final SumThenDiffComparator INSTANCE = new SumThenDiffComparator();
 39 
 40         public int compare(Obstacle o1, Obstacle o2) {
 41             int s1 = o1.x + o1.y;
 42             int s2 = o2.x + o2.y;
 43             if (s1 != s2)
 44                 return s1 - s2;
 45             s1 = o1.x - o1.y;
 46             s2 = o2.x - o2.y;
 47             return s1 - s2;
 48         }
 49     }
 50 
 51     static class DiffThenSumComparator implements Comparator<Obstacle> {
 52         static final DiffThenSumComparator INSTANCE = new DiffThenSumComparator();
 53 
 54         public int compare(Obstacle o1, Obstacle o2) {
 55             int s1 = o1.x - o1.y;
 56             int s2 = o2.x - o2.y;
 57             if (s1 != s2)
 58                 return s1 - s2;
 59             s1 = o1.x + o1.y;
 60             s2 = o2.x + o2.y;
 61             return s1 - s2;
 62         }
 63     }
 64 
 65     static class Obstacles {
 66         Obstacle[] bySum;
 67         Obstacle[] byDiff;
 68         int maxx;
 69         int maxy;
 70 
 71         public Obstacles(Obstacle[] ob, int maxx, int maxy) {
 72             this.maxx = maxx;
 73             this.maxy = maxy;
 74             bySum = ob.clone();
 75             Arrays.sort(bySum, SumThenDiffComparator.INSTANCE);
 76             byDiff = ob.clone();
 77             Arrays.sort(byDiff, DiffThenSumComparator.INSTANCE);
 78         }
 79 
 80         public boolean haveObstacle(int x, int y) {
 81             if (x <= 0 || x > maxx || y <= 0 || y > maxy) return true;
 82             Obstacle cur = new Obstacle();
 83             cur.x = x;
 84             cur.y = y;
 85             return Arrays.binarySearch(bySum, cur, SumThenDiffComparator.INSTANCE) >= 0;
 86         }
 87 
 88         public Obstacle getNext(int x, int y, int dx, int dy) {
 89             Obstacle cur = new Obstacle();
 90             cur.x = x;
 91             cur.y = y;
 92             if (dx == dy) {
 93                 int pos = Arrays.binarySearch(byDiff, cur, DiffThenSumComparator.INSTANCE);
 94                 if (pos >= 0) throw new RuntimeException();
 95                 pos = -(pos + 1);
 96                 if (dx > 0) {
 97                     if (pos < byDiff.length && x - y == byDiff[pos].x - byDiff[pos].y)
 98                         return byDiff[pos];
 99                     else
100                         return getBoundary(x, y, dx, dy);
101                 } else {
102                     --pos;
103                     if (pos >= 0 && x - y == byDiff[pos].x - byDiff[pos].y)
104                         return byDiff[pos];
105                     else
106                         return getBoundary(x, y, dx, dy);
107                 }
108             } else {
109                 int pos = Arrays.binarySearch(bySum, cur, SumThenDiffComparator.INSTANCE);
110                 if (pos >= 0) {
111                     throw new RuntimeException();
112                 }
113                 pos = -(pos + 1);
114                 if (dx > 0) {
115                     if (pos < bySum.length && x + y == bySum[pos].x + bySum[pos].y)
116                         return bySum[pos];
117                     else
118                         return getBoundary(x, y, dx, dy);
119                 } else {
120                     --pos;
121                     if (pos >= 0 && x + y == bySum[pos].x + bySum[pos].y)
122                         return bySum[pos];
123                     else
124                         return getBoundary(x, y, dx, dy);
125                 }
126             }
127         }
128 
129         private Obstacle getBoundary(int x, int y, int dx, int dy) {
130             int times = Integer.MAX_VALUE;
131             if (dx > 0) times = Math.min(times, maxx + 1 - x); else times = Math.min(times, x);
132             if (dy > 0) times = Math.min(times, maxy + 1 - y); else times = Math.min(times, y);
133             Obstacle res = new Obstacle();
134             res.x = x + times * dx;
135             res.y = y + times * dy;
136             return res;
137         }
138     }
139 
140     Obstacles obstacles;
141     int xs;
142     int ys;
143     int dx;
144     int dy;
145     List<Segment> segments = new ArrayList<Segment>();
146 
147     static class Segment implements Comparable<Segment> {
148         int x1;
149         int y1;
150         int x2;
151         int y2;
152 
153         Segment(int x1, int y1, int x2, int y2) {
154             if (x1 < x2) {
155                 this.x1 = x1;
156                 this.y1 = y1;
157                 this.x2 = x2;
158                 this.y2 = y2;
159             } else {
160                 this.x1 = x2;
161                 this.y1 = y2;
162                 this.x2 = x1;
163                 this.y2 = y1;
164             }
165         }
166 
167         public int compareTo(Segment o) {
168             if (x1 != o.x1) return x1 - o.x1;
169             if (y1 != o.y1) return y1 - o.y1;
170             if (x2 != o.x2) return x2 - o.x2;
171             return y2 - o.y2;
172         }
173     }
174 
175     public void solve(int testNumber, InputReader in, PrintWriter out) {
176         int maxx = in.nextInt();
177         int maxy = in.nextInt();
178         int k = in.nextInt();
179         Obstacle[] ob = new Obstacle[k];
180         for (int i = 0; i < k; ++i) {
181             ob[i] = new Obstacle();
182             ob[i].x = in.nextInt();
183             ob[i].y = in.nextInt();
184         }
185         xs = in.nextInt();
186         ys = in.nextInt();
187         String dir = in.next();
188         if (dir.equals("NE")) {
189             dx = -1;
190             dy = 1;
191         } else if (dir.equals("NW")) {
192             dx = -1;
193             dy = -1;
194         } else if (dir.equals("SE")) {
195             dx = 1;
196             dy = 1;
197         } else if (dir.equals("SW")) {
198             dx = 1;
199             dy = -1;
200         } else throw new RuntimeException();
201         long res = doit(maxx, maxy, ob);
202         out.println(res);
203     }
204 
205     private long doit(int maxx, int maxy, Obstacle[] ob) {
206         shuffle(ob);
207         obstacles = new Obstacles(ob, maxx, maxy);
208         oneStep();
209         int exs = xs;
210         int eys = ys;
211         int edx = dx;
212         int edy = dy;
213         segments.clear();
214         do {
215             oneStep();
216         } while (xs != exs || ys != eys || dx != edx || dy != edy);
217         List<Segment> plus = new ArrayList<Segment>();
218         List<Segment> minus = new ArrayList<Segment>();
219         for (Segment s : segments) {
220             if (s.x1 + s.y1 == s.x2 + s.y2) {
221                 plus.add(s);
222             } else {
223                 minus.add(s);
224             }
225         }
226         Collections.sort(plus);
227         Collections.sort(minus);
228         int cnt = 0;
229         for (int i = 0; i < plus.size(); ++i) {
230             if (i == 0 || plus.get(i).compareTo(plus.get(i - 1)) > 0)
231                 plus.set(cnt++, plus.get(i));
232         }
233         while (plus.size() > cnt) plus.remove(plus.size() - 1);
234         cnt = 0;
235         for (int i = 0; i < minus.size(); ++i) {
236             if (i == 0 || minus.get(i).compareTo(minus.get(i - 1)) > 0)
237                 minus.set(cnt++, minus.get(i));
238         }
239         while (minus.size() > cnt) minus.remove(minus.size() - 1);
240         long res = 0;
241         for (Segment x : plus) {
242             res += Math.abs(x.x1 - x.x2) + 1;
243         }
244         for (Segment x : minus) {
245             res += Math.abs(x.x1 - x.x2) + 1;
246         }
247         return res;
248     }
249 
250     private void oneStep() {
251         Obstacle meet = obstacles.getNext(xs, ys, dx, dy);
252         int px = meet.x - dx;
253         int py = meet.y - dy;
254         segments.add(new Segment(xs, ys, px, py));
255         boolean haveX = obstacles.haveObstacle(px, meet.y);
256         boolean haveY = obstacles.haveObstacle(meet.x, py);
257         if (haveX && !haveY) {
258             xs = meet.x;
259             ys = py;
260             dy = -dy;
261         } else if (haveY && !haveX) {
262             xs = px;
263             ys = meet.y;
264             dx = -dx;
265         } else {
266             xs = px;
267             ys = py;
268             dx = -dx;
269             dy = -dy;
270         }
271     }
272 
273     Random random = new Random(System.currentTimeMillis() + 438467315);
274 
275     private void shuffle(Obstacle[] x) {
276         for (int i = 0; i < x.length; ++i) {
277             int j = i + random.nextInt(x.length - i);
278             Obstacle tmp = x[i];
279             x[i] = x[j];
280             x[j] = tmp;
281         }
282     }
283 }
284 
285 class InputReader {
286     public BufferedReader reader;
287     public StringTokenizer tokenizer;
288 
289     public InputReader(InputStream stream) {
290         reader = new BufferedReader(new InputStreamReader(stream));
291         tokenizer = null;
292     }
293 
294     public String next() {
295         while (tokenizer == null || !tokenizer.hasMoreTokens()) {
296             try {
297                 tokenizer = new StringTokenizer(reader.readLine());
298             } catch (IOException e) {
299                 throw new RuntimeException(e);
300             }
301         }
302         return tokenizer.nextToken();
303     }
304 
305     public int nextInt() {
306         return Integer.parseInt(next());
307     }
308 
309     }

 

posted @ 2013-06-02 21:09  芒果布丁  阅读(413)  评论(0编辑  收藏  举报