Submission #5186
Source Code Expand
import std.stdio; import std.math; import std.algorithm; class Point{ long x, y; this(long x, long y){ this.x = x; this.y = y; } Point opSub(Point p){ return new Point(x - p.x, y - p.y); } override bool opEquals(Object o){ return x == (cast(Point)o).x && y == (cast(Point)o).y; } } long iprod(Point a, Point b){ return a.x * b.x + a.y * b.y; } long oprod(Point a, Point b){ return a.x * b.y - b.x * a.y; } long sq(long x){ return x * x; } long abs2(Point a){ return sq(a.x) + sq(a.y); } real getDistance(Point a){ return sqrt(cast(real)abs2(a)); } real getDistance(Point a, Point b){ return getDistance(a - b); } int ccw(Point a, Point b, Point c){ auto nb = b - a, nc = c - a; if( oprod(nb, nc) > 0 ){ return +1; } if( oprod(nb, nc) < 0 ){ return -1; } if( iprod(nb, nc) < 0 ){ return +2; } if( abs2(nb) < abs2(nc) ){ return -2; } return 0; } int N, start, goal; Point[] ls, rs; int[] lx, rx; void init(){ scanf("%d%d%d", &N, &start, &goal); ls = new Point[](N + 1); rs = new Point[](N + 1); lx = new int[](N + 1); rx = new int[](N + 1); for(int i=0; i<=N; ++i){ scanf("%d%d", &lx[i], &rx[i]); ls[i] = new Point(lx[i], i); rs[i] = new Point(rx[i], i); } } //[from, to] : closed, ls[from] == rs[from], ls[to] == rs[to] real calc(int from, int to){ if(to - from == 1){ return getDistance(ls[from], ls[to]); } Point cur = ls[from], tar = ls[to]; auto es = [cur]; for(int i=from+1; i<to; ++i){ if( ccw(cur, ls[i], tar) == +1 ){ es ~= ls[i]; cur = ls[i]; } } cur = rs[from]; for(int i=from+1; i<to; ++i){ if( ccw(cur, rs[i], tar) == -1 ){ es ~= rs[i]; cur = rs[i]; } } es ~= tar; if(es.length == 2){ return getDistance(es[0], es[1]); } sort!"a.y < b.y"(es); real ans = 0.0; for(int i=0; i<es.length-1; ++i){ int y1 = cast(int)es[i].y, y2 = cast(int)es[i+1].y; ls[y1] = rs[y1] = es[i]; ls[y2] = rs[y2] = es[i+1]; ans += calc(y1, y2); } return ans; } Point[] convexHullLeft(Point[] ps){ const int n = ps.length; int k = 0; Point[] ret = new Point[](2*n); for(int i=0; i<n; ++i){ for(;k>1 && oprod(ret[k-1] - ret[k-2], ps[i] - ret[k-1]) <= 0; --k){} ret[k++] = ps[i]; } return ret[0..k]; } Point[] convexHullRight(Point[] ps){ const int n = ps.length; int k = 0; Point[] ret = new Point[](2*n); for(int i=0; i<n; ++i){ for(;k>1 && oprod(ret[k-1] - ret[k-2], ps[i] - ret[k-1]) >= 0; --k){} ret[k++] = ps[i]; } return ret[0..k]; } real calcLeft(int from, int to, bool fin = false){ if(to - from == 1){ //writeln(ls[from].x, ",", ls[from].y, " -> ", ls[to].x, ",", ls[to].y); return getDistance(ls[from], ls[to]); } /* Point cur = ls[from], tar = ls[to]; auto es = [cur]; for(int i=from+1; i<to; ++i){ if( ccw(cur, ls[i], tar) == +1 ){ es ~= ls[i]; cur = ls[i]; } } es ~= tar; */ auto es = convexHullLeft(ls[from..to+1]); /* writeln("left: ", from, " ", to); foreach(e ; es){ writeln(e.x, " ", e.y); } writeln; */ if(fin && es.length == 2){ //writeln(es[0].x, ",", es[0].y, " -> ", es[1].x, ",", es[1].y); return getDistance(es[0], es[1]); } else{ real ans = 0.0; for(int i=0; i<es.length-1; ++i){ int y1 = cast(int)es[i].y, y2 = cast(int)es[i+1].y; ls[y1] = rs[y1] = es[i]; ls[y2] = rs[y2] = es[i+1]; ans += calcRight(y1, y2); } return ans; } } real calcRight(int from, int to){ if(to - from == 1){ //writeln(rs[from].x, ",", rs[from].y, " -> ", rs[to].x, ",", rs[to].y); return getDistance(rs[from], rs[to]); } /* Point cur = rs[from], tar = rs[to]; auto es = [cur]; for(int i=from+1; i<to; ++i){ if( ccw(cur, rs[i], tar) == -1 ){ es ~= rs[i]; cur = rs[i]; } } es ~= tar; */ auto es = convexHullRight(rs[from..to+1]); /* writeln("right: ", from, " ", to); foreach(e ; es){ writeln(e.x, " ", e.y); } writeln; */ if(es.length == 2){ //writeln(es[0].x, ",", es[0].y, " -> ", es[1].x, ",", es[1].y); return getDistance(es[0], es[1]); } else{ real ans = 0.0; for(int i=0; i<es.length-1; ++i){ int y1 = cast(int)es[i].y, y2 = cast(int)es[i+1].y; ls[y1] = rs[y1] = es[i]; ls[y2] = rs[y2] = es[i+1]; ans += calcLeft(y1, y2, true); } return ans; } } real bad_solver(){ long cx = start, cy = 0; real ans = 0.0; for(int i=1; i<N; ++i){ if(cx < lx[i]){ writeln(cx, ",", cy, " -> ", ls[i].x, ",", ls[i].y); ans += getDistance(new Point(cx, cy), ls[i]); cx = ls[i].x; cy = ls[i].y; } else if(cx > rx[i]){ writeln(cx, ",", cy, " -> ", rs[i].x, ",", rs[i].y); ans += getDistance(new Point(cx, cy), rs[i]); cx = rs[i].x; cy = rs[i].y; } } writeln(cx, ",", cy, " -> ", rs[N].x, ",", rs[N].y); ans += getDistance(new Point(cx, cy), rs[N]); return ans; } real solve(){ ls[0] = rs[0] = new Point(start, 0); ls[N] = rs[N] = new Point(goal, N); //writeln(bad_solver); return calcLeft(0, N); //return calc(0, N); //return min(bad_solver, bad_solver2, calc(0, N)); } void main(){ init; writefln("%.12f", solve); }
Submission Info
Submission Time | |
---|---|
Task | D - レースゲーム |
User | komiya |
Language | D (DMD 2.060) |
Score | 0 |
Code Size | 5287 Byte |
Status | CE |
Compile Error
./Main.d(121): Error: cannot implicitly convert expression (ps.length) of type ulong to const(int) ./Main.d(132): Error: cannot implicitly convert expression (ps.length) of type ulong to const(int)