Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.*;
- import java.security.*;
- import java.util.*;
- class Wall {
- public P start, end;
- public long minx, miny;
- public long maxx, maxy;
- public Wall(P st, P e) {
- start = st;
- end = e;
- minx = st.x < e.x ? st.x : e.x;
- maxx = st.x > e.x ? st.x : e.x;
- miny = st.y < e.y ? st.y : e.y;
- maxy = st.y > e.y ? st.y : e.y;
- }
- public String toString() {
- return "[" + start + " - " + end + "]";
- }
- // check whether a-b segment intersects c-d segment (1-dimension)
- public static boolean boundBoxIntersect(long a, long b, long c, long d) {
- return Math.max(Math.min(a, b), Math.min(c, d)) <=
- Math.min(Math.max(a, b), Math.max(c, d));
- }
- // calculate oriented area of ABC triangle
- private static long orientedAreaSign(P a, P b, P c) {
- long area = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
- return area == 0 ? 0 : area / Math.abs(area);
- }
- public boolean intersect(Wall other) {
- // two segments intersect if 1) their bounding boxes intersect and 2) oriented areas of triangles have different signs
- return
- //boundBoxIntersect(start.x, end.x, other.start.x, other.end.x) &&
- //boundBoxIntersect(start.y, end.y, other.start.y, other.end.y) &&
- Math.max(minx, other.minx) <= Math.min(maxx, other.maxx) &&
- Math.max(miny, other.miny) <= Math.min(maxy, other.maxy) &&
- orientedAreaSign(start, end, other.start) * orientedAreaSign(start, end, other.end) <= 0 &&
- orientedAreaSign(other.start, other.end, start) * orientedAreaSign(other.start, other.end, end) <= 0;
- }
- }
- // the lights can only be placed in lattice points 0.00, 0.01, ..., 0.99, 1.00
- // illumination is checked in points between lattice points 0.005, 0.015, ...
- class P {
- public static final double eps = 1E-6;
- public static final int f = 100;// the number of parts we divide each unit of length into
- public long x, y;
- private double xd, yd;
- public boolean hasConverted = false;
- public P() {};
- public P(long x1, long y1) {
- x = x1;
- y = y1;
- }
- private long P2(long a) {
- return a * a;
- }
- public long dist2(P other) {
- return P2(x - other.x) + P2(y - other.y);
- }
- // to define whether the point is within lighting radius of the light
- public boolean near(P other, long d) {
- return dist2(other) <= P2(2 * d * f);
- }
- public String toString() {
- if(!hasConverted) {
- xd = x / 2.0 / f;
- yd = y / 2.0 / f;
- hasConverted = true;
- }
- return "(" + xd + "," + yd + ")";
- }
- }
- class Map {
- String[] map;
- int S;
- int D;
- int L;
- ArrayList<Wall> walls;
- ArrayList<ArrayList<Wall>> nearbyWalls;
- Map(String[] map, int S, int D, int L) {
- this.map = map;
- this.S = S;
- this.D = D;
- this.L = L;
- this.walls = extractWalls();
- this.nearbyWalls = new ArrayList<ArrayList<Wall>>();
- for(int r=0; r < S; r++) {
- for(int c=0; c < S; c++) {
- ArrayList<Wall> nearby = new ArrayList<Wall>();
- for (int i = 0; i < walls.size(); ++i) {
- int boxX1 = Math.max(1, c*P.f*2 + 1 - D*P.f*2);
- int boxX2 = Math.min(S*P.f*2-1, c*P.f*2 + P.f*2 -1 + D*P.f*2);
- int boxY1 = Math.max(1, r*P.f*2 + 1 - D*P.f*2);
- int boxY2 = Math.min(S*P.f*2-1, r*P.f*2 + P.f*2 -1 + D*P.f*2);
- Wall w =walls.get(i);
- if (Wall.boundBoxIntersect(boxX1, boxX2, w.start.x, w.end.x) &&
- Wall.boundBoxIntersect(boxY1, boxY2, w.start.y, w.end.y)) {
- nearby.add(w);
- }
- }
- //System.err.println("Putting " + (r*S+c));
- nearbyWalls.add(nearby);
- //System.err.println("Putting2 " + (nearbyWalls.get(r*S+c)));
- }
- }
- }
- boolean isWall(int y, int x) {
- return map[y].charAt(x) == '#';
- }
- ArrayList<Wall> getNearbyWalls(P p) {
- //System.err.println("Getting1 " + nearbyWalls);
- int g = (int) ((p.y / (P.f*2)) * S + (p.x / (P.f*2)));
- //System.err.println("Getting " + ((p.y / (P.f*2)) * S + (p.x / (P.f*2))));
- ArrayList<Wall> ret = nearbyWalls.get(g);
- if(ret == null) {
- System.err.println("invalid point p=" + p);
- }
- return ret;
- }
- ArrayList<Wall> extractWalls() {
- ArrayList<Wall> walls = new ArrayList<>();
- // we don't need outer walls (walls between map and outside of the map), since all light it within the map
- // a wall is a vertical or horizontal line which on each 1-length piece is bordered by both wall and empty space
- // horizontal walls
- for (int i = 0; i < S - 1; ++i) {
- int j = 0;
- while (j < S) {
- // check whether j is start of the wall
- if (map[i].charAt(j) == map[i+1].charAt(j)) {
- j++;
- continue;
- }
- // if it is, keep increasing it until the wall ends
- P start = new P(j * 2 * P.f, (i+1) * 2 * P.f);
- while (j < S && map[i].charAt(j) != map[i+1].charAt(j)) {
- j++;
- }
- P end = new P(j * 2 * P.f, (i+1) * 2 * P.f);
- Wall w = new Wall(start, end);
- walls.add(w);
- }
- }
- // vertical walls
- for (int j = 0; j < S - 1; ++j) {
- int i = 0;
- while (i < S) {
- // check whether j is start of the wall
- if (map[i].charAt(j) == map[i].charAt(j+1)) {
- i++;
- continue;
- }
- // if it is, keep increasing it until the wall ends
- P start = new P((j+1) * 2 * P.f, i * 2 * P.f);
- while (i < S && map[i].charAt(j) != map[i].charAt(j+1)) {
- i++;
- }
- P end = new P((j+1) * 2 * P.f, i * 2 * P.f);
- Wall w = new Wall(start, end);
- walls.add(w);
- }
- }
- return walls;
- }
- }
- class Scene {
- int S;
- Map map;
- int D;
- int L;
- long startTime = System.currentTimeMillis();
- P[] lights = new P[L];
- P[] maxLights = new P[L];
- int[] lightContrib = new int[L];
- int[] lightContribWoOverlap = new int[L];
- int[] maxLightContrib = new int[L];
- int[] maxLightContribWoOverlap = new int[L];
- int maxScore;
- int tries = 0;
- int subdiv;
- int[][] points = new int[S * subdiv][S * subdiv];
- int[][] maxPoints = new int[S * subdiv][S * subdiv];
- int nTotal;
- P[][] pointsLoc;
- int lastLightMoved = -1;
- int score;
- Scene(){}
- void init(Map map, int S, int D, int L, int subdivPoints) {
- this.S = S;
- this.map = map;
- this.D = D;
- this.L = L;
- System.err.println("S = " + S);
- System.err.println("D = " + D);
- System.err.println("L = " + L);
- lights = new P[L];
- maxLights = new P[L];
- lightContrib = new int[L];
- lightContribWoOverlap = new int[L];
- maxLightContrib = new int[L];
- maxLightContribWoOverlap = new int[L];
- incSubdiv(subdivPoints);
- points = new int[S * subdiv][S * subdiv];
- maxPoints = new int[S * subdiv][S * subdiv];
- pointsLoc = new P[S * subdiv][S * subdiv];
- for(int y=0; y < S * subdiv; y++) {
- for(int x=0; x < S * subdiv; x++) {
- pointsLoc[y][x] = new P(x * P.f * 2 / subdiv + P.f / subdiv, y * P.f * 2 / subdiv + P.f / subdiv);
- }
- }
- nTotal = getFloorPoints();
- markWallPoints();
- }
- void incSubdiv(int maxSamplePoints) {
- int oldsubdiv = subdiv;
- subdiv = (int)Math.sqrt(maxSamplePoints / (S*S));
- if(subdiv >= 100) {
- subdiv = 100;
- } else if(subdiv >= 50) {
- subdiv = 50;
- } else if(subdiv >= 25) {
- subdiv = 25;
- } else if(subdiv >= 20) {
- subdiv = 20;
- } else if(subdiv >= 10) {
- subdiv = 10;
- } else if(subdiv >= 5) {
- subdiv = 5;
- } else if(subdiv >= 4) {
- subdiv = 4;
- } else if(subdiv >= 2) {
- subdiv = 2;
- } else {
- subdiv = 1;
- }
- // Don't ever decrease
- if(subdiv <= oldsubdiv) {
- subdiv = oldsubdiv;
- return;
- }
- points = new int[S * subdiv][S * subdiv];
- maxPoints = new int[S * subdiv][S * subdiv];
- pointsLoc = new P[S * subdiv][S * subdiv];
- for(int y=0; y < S * subdiv; y++) {
- for(int x=0; x < S * subdiv; x++) {
- pointsLoc[y][x] = new P(x * P.f * 2 / subdiv + P.f / subdiv, y * P.f * 2 / subdiv + P.f / subdiv);
- }
- }
- clearLights();
- addLights();
- maxScore=illuminatedPoints();
- nTotal = getFloorPoints();
- markWallPoints();
- save();
- if(subdiv != oldsubdiv) System.err.println("setting subdiv to " + subdiv);
- }
- void markWallPoints() {
- // mark wall points beforehand
- for (int r = 0; r < S; ++r)
- for (int c = 0; c < S; ++c) {
- if (!map.isWall(r, c))
- continue;
- for (int x = c * subdiv; x < (c + 1) * subdiv; ++x)
- for (int y = r * subdiv; y < (r + 1) * subdiv; ++y) {
- points[y][x] = -1;
- }
- }
- //System.err.println("Done marking walls");
- }
- void clearPoints() {
- for (int r = 0; r < S * subdiv; ++r) {
- for (int c = 0; c < S * subdiv; ++c) {
- if(points[r][c] != -1) points[r][c] = 0;
- }
- }
- }
- void clearLight(int lightIdx) {
- P light = lights[lightIdx];
- if(light == null) return;
- long boxX1 = Math.max(0, light.x - 2 * P.f * D);
- long boxX2 = Math.min(2 * (P.f * S - 1), light.x + 2 * P.f * D);
- long boxY1 = Math.max(0, light.y - 2 * P.f * D);
- long boxY2 = Math.min(2 * (P.f * S - 1), light.y + 2 * P.f * D);
- for (int y = (int)boxY1 * subdiv / P.f / 2; y <= boxY2 * subdiv / P.f / 2; ++y)
- for (int x = (int)boxX1 * subdiv / P.f / 2; x <= boxX2 * subdiv / P.f / 2; ++x) {
- if(points[y][x] != -1 && (points[y][x] & (1<<lightIdx)) != 0) {
- points[y][x] &= ~(1<<lightIdx);
- }
- }
- lightContrib[lightIdx] = 0;
- lightContribWoOverlap[lightIdx] = 0;
- // for (int r = 0; r < S * subdiv; ++r) {
- // for (int c = 0; c < S * subdiv; ++c) {
- // if(points[r][c] != -1 && (points[r][c] & (1<<lightIdx)) != 0) {
- // points[r][c] &= ~(1<<lightIdx);
- // }
- // }
- // }
- }
- void clearLights() {
- for (int r = 0; r < S * subdiv; ++r) {
- for (int c = 0; c < S * subdiv; ++c) {
- if(points[r][c] != -1) {
- points[r][c] = 0;
- }
- }
- }
- for(int l=0; l < L; l++) {
- lightContrib[l] = 0;
- lightContribWoOverlap[l] = 0;
- }
- }
- int getFloorPoints() {
- int nIllum = 0, nTotal = 0;
- for (int r = 0; r < S; ++r)
- for (int c = 0; c < S; ++c) {
- if (map.isWall(r, c))
- continue;
- nTotal += subdiv * subdiv;
- }
- return nTotal;
- }
- int illuminatedPoints() {
- //System.err.println("Done lighting. Counting points...");
- // check all points within the map and count illuminated ones
- int nIllum = 0, nTotal = 0;
- for (int r = 0; r < S; ++r)
- for (int c = 0; c < S; ++c) {
- if (map.isWall(r, c))
- continue;
- for (int x = 0; x < subdiv; ++x)
- for (int y = 0; y < subdiv; ++y) {
- // the point we need to check is middle of square of size 1/P.f
- nTotal++;
- if (points[r * subdiv + y][c * subdiv + x] > 0)
- nIllum++;
- }
- }
- // int nIllum2 = 0;
- // for(int l=0; l < L; l++) {
- // nIllum2 += lightContribWoOverlap[l];
- // }
- score = nIllum;
- return score;
- }
- void addLights() {
- for(int lightIdx = 0; lightIdx < lights.length; lightIdx++) {
- addLight(lightIdx);
- }
- }
- boolean isPointLitByLight(ArrayList<Wall> localWalls, int lightIdx, P point) {
- P light = lights[lightIdx];
- return isPointLitByLight(localWalls, light, point);
- }
- boolean isPointLitByLight(ArrayList<Wall> localWalls, P light, P point) {
- if (!light.near(point, D))
- return false;
- Wall beam = new Wall(point, light);
- for (int i=0; i < localWalls.size(); i++) {
- //if (beam.intersect(walls.get(ind))) {
- if (localWalls.get(i).intersect(beam)) {
- return false;
- }
- }
- return true;
- }
- boolean isPointLitByLightInefficient(P light, P point) {
- // first, find bounding box of the light and only get the walls which intersect it
- long boxX1 = Math.max(0, light.x - 2 * P.f * D);
- long boxX2 = Math.min(2 * (P.f * S - 1), light.x + 2 * P.f * D);
- long boxY1 = Math.max(0, light.y - 2 * P.f * D);
- long boxY2 = Math.min(2 * (P.f * S - 1), light.y + 2 * P.f * D);
- ArrayList<Wall> walls = map.getNearbyWalls(light);
- return isPointLitByLight(walls, light, point);
- }
- void addLightInCell(ArrayList<Wall> localWalls, int lightIdx, int x1, int y1, int x2, int y2) {
- if(x2 - x1 <= 2 || y2 - y1 <= 2) {
- for(int y=y1; y < y2; y++) {
- for(int x=x1; x < x2; x++) {
- P point = new P(x * P.f * 2 / subdiv + P.f / subdiv, y * P.f * 2 / subdiv + P.f / subdiv);
- if(isPointLitByLight(localWalls, lightIdx, point)){
- if(points[y][x] == 0) {
- lightContribWoOverlap[lightIdx]++;
- }
- points[y][x] |= (1 << lightIdx);
- lightContrib[lightIdx]++;
- }
- }
- }
- return;
- }
- long mul = P.f * 2 / subdiv;
- long add = P.f / subdiv;
- //new P(x * P.f * 2 / subdiv + P.f / subdiv, y * P.f * 2 / subdiv + P.f / subdiv);
- P tl = new P(x1 * mul + add, y1 * mul + add);
- P tr = new P(x2 * mul + add, y1 * mul + add);
- P bl = new P(x1 * mul + add, y2 * mul + add);
- P br = new P(x2 * mul + add, y2 * mul + add);
- boolean tlLit = isPointLitByLight(localWalls, lightIdx, tl);
- boolean trLit = isPointLitByLight(localWalls, lightIdx, tr);
- boolean blLit = isPointLitByLight(localWalls, lightIdx, bl);
- boolean brLit = isPointLitByLight(localWalls, lightIdx, br);
- if(tlLit && trLit && blLit && brLit) {
- //System.err.printf("Whole square (%d %d) (%d %d)%n", x1, y1, x2, y2);
- for(int y=y1; y < y2; y++) {
- for(int x=x1; x < x2; x++) {
- if(points[y][x] == 0) {
- lightContribWoOverlap[lightIdx]++;
- }
- points[y][x] |= (1 << lightIdx);
- lightContrib[lightIdx]++;
- }
- }
- return;
- }
- for(int y=y1; y < y2; y++) {
- for(int x=x1; x < x2; x++) {
- P point = pointsLoc[y][x];
- if(isPointLitByLight(localWalls, lightIdx, point)){
- if(points[y][x] == 0) {
- lightContribWoOverlap[lightIdx]++;
- }
- points[y][x] |= (1 << lightIdx);
- lightContrib[lightIdx]++;
- }
- }
- }
- }
- void addLight(int lightIdx) {
- P light = lights[lightIdx];
- if(light == null) return;
- // first, find bounding box of the light and only get the walls which intersect it
- long boxX1 = Math.max(0, light.x - 2 * P.f * D);
- long boxX2 = Math.min(2 * (P.f * S - 1), light.x + 2 * P.f * D);
- long boxY1 = Math.max(0, light.y - 2 * P.f * D);
- long boxY2 = Math.min(2 * (P.f * S - 1), light.y + 2 * P.f * D);
- //System.err.println("Doing light #" + lightIdx);
- // now iterate throw points in the bounding box and see whether they are illuminated
- // using only local walls, not the whole list
- //
- // the far bound could be optimized, <= might not be needed
- // ArrayList<Wall> walls = map.getNearbyWalls(light);
- // for(int c=(int)(boxX1 / (P.f*2)); c < (boxX2 + P.f*2 - 1) / (P.f*2); c++) {
- // for(int r=(int)(boxY1 / (P.f*2)); r < (boxY2 + P.f*2 - 1) / (P.f*2); r++) {
- // ArrayList<Wall> walls2 = map.getNearbyWalls(light);
- // addLightInCell(walls, lightIdx,
- // c * subdiv,
- // r * subdiv,
- // (c+1) * subdiv,
- // (r+1) * subdiv);
- // }
- // }
- for (int y = (int)boxY1 * subdiv / P.f / 2; y <= boxY2 * subdiv / P.f / 2; ++y)
- for (int x = (int)boxX1 * subdiv / P.f / 2; x <= boxX2 * subdiv / P.f / 2; ++x) {
- if (points[y][x] == -1) {
- // point is part of a wall
- continue;
- }
- P point = pointsLoc[y][x];
- boolean lit = isPointLitByLightInefficient(light, point);
- if (lit) {
- if(points[y][x] == 0) {
- lightContribWoOverlap[lightIdx]++;
- }
- points[y][x] |= (1 << lightIdx);
- lightContrib[lightIdx]++;
- }
- }
- lastLightMoved = lightIdx;
- //System.err.println("Light #" + lightIdx + " is " + lightContribWoOverlap[lightIdx]);
- }
- void save() {
- // System.err.println("Save");
- maxScore = score;
- System.arraycopy(lights, 0, maxLights,0, L);
- for(int r=0; r < S*subdiv; r++) System.arraycopy(points[r],0,maxPoints[r],0,S*subdiv);
- System.arraycopy(lightContrib,0,maxLightContrib,0,L);
- System.arraycopy(lightContribWoOverlap,0,maxLightContribWoOverlap,0,L);
- }
- void restore() {
- // System.err.println("Restore");
- score = maxScore;
- lights = maxLights.clone();
- System.arraycopy(maxLights, 0, lights,0, L);
- for(int r=0; r < S*subdiv; r++) System.arraycopy(maxPoints[r],0,points[r],0,S*subdiv);
- System.arraycopy(maxLightContrib,0,lightContrib,0,L);
- System.arraycopy(maxLightContribWoOverlap,0,lightContribWoOverlap,0,L);
- }
- int getLeastContribLight() {
- int lightIdx=0;
- int minContrib=lightContrib[0];
- for(int l=0; l< L; l++) {
- if(lightContrib[l] < minContrib) {
- lightIdx = l;
- minContrib = lightContrib[l];
- }
- }
- return lightIdx;
- }
- int getLeastContribLightWoOverlap() {
- int lightIdx=0;
- int minContrib=lightContribWoOverlap[0];
- for(int l=0; l< L; l++) {
- if(lightContribWoOverlap[l] < minContrib) {
- lightIdx = l;
- minContrib = lightContribWoOverlap[l];
- }
- }
- return lightIdx;
- }
- P randLight(Random r) {
- int xw, xdec, yw, ydec;
- P light = new P();
- do {
- xw = r.nextInt(S);
- xdec = r.nextInt(P.f);
- yw = r.nextInt(S);
- ydec = r.nextInt(P.f);
- if(map.isWall(yw, xw)) continue;
- if(xdec == 0) {
- if(xw > 0) {
- if(map.isWall(yw, xw-1)) continue;
- } else {
- continue;
- }
- }
- if(ydec == 0) {
- if(yw > 0) {
- if(map.isWall(yw-1, xw)) continue;
- } else {
- continue;
- }
- }
- break;
- } while(true);
- return new P(xw*2*P.f + xdec*2, yw*2*P.f + ydec*2);
- }
- void moveLightToRand(Random r, int lightIdx) {
- clearLight(lightIdx);
- lights[lightIdx] = randLight(r);
- addLight(lightIdx);
- }
- boolean isLightValid(P light) {
- if(light.x <= 0) return false;
- if(light.y <= 0) return false;
- if(light.x >= P.f*2*S) return false;
- if(light.y >= P.f*2*S) return false;
- int xw = (int) (light.x/(2*P.f));
- int xdec = (int) (light.x%(2*P.f));
- int yw = (int) (light.y/(2*P.f));
- int ydec = (int) (light.y%(2*P.f));
- if(map.isWall(yw,xw)) return false;
- if(xdec == 0) {
- if(xw > 0) {
- if(map.isWall(yw,xw-1)) return false;
- } else {
- return false;
- }
- }
- if(ydec == 0) {
- if(yw > 0) {
- if(map.isWall(yw-1,xw)) return false;
- } else {
- return false;
- }
- }
- return true;
- }
- boolean tieBreakMax(Random r) {
- long count=0;
- long maxCount=0;
- // for(int i=0; i < 500; i++) {
- // P p = randLight(r);
- // boolean lit=false, litMax = false;
- // for(int l=0; l < L; l++) {
- // if(!lit) lit = isPointLitByLightInefficient(lights[l], p);
- // if(!litMax) litMax = isPointLitByLightInefficient(maxLights[l], p);
- // }
- // if(lit) count++;
- // if(litMax) maxCount++;
- // if(count > maxCount){
- // System.err.println("TIE BREAKKKEERRR " + count + ", " + maxCount);
- // return true;
- // }
- // if(maxCount < count) return false;
- // for(int y=0; y < S; y++) {
- // for(int x=0; x < S; x++) {
- // if(!map.isWall(y,x)) {
- // P[] ps = new P[4];
- // ps[0] = new P(x*P.f*2 + 1, y*P.f*2 + 1);
- // ps[1] = new P(x*P.f*2 + P.f*2 -1, y*P.f*2 + 1);
- // ps[2] = new P(x*P.f*2 + 1, y*P.f*2 + P.f*2 -1);
- // ps[3] = new P(x*P.f*2 + P.f*2 -1, y*P.f*2 + P.f*2 -1);
- // boolean[] lit = new boolean[4];
- // boolean[] mlit = new boolean[4];
- // for(int pnum=0; pnum < 4; pnum++) {
- // for(int l=0; l < L; l++) {
- // if(!lit[pnum] && isPointLitByLightInefficient(lights[l], ps[pnum])) {
- // count++;
- // lit[pnum]=true;
- // }
- // if(!mlit[pnum] && isPointLitByLightInefficient(maxLights[l], ps[pnum])) {
- // maxCount++;
- // mlit[pnum]=true;
- // }
- // }
- // }
- // }
- // }
- // }
- //
- // if(count > maxCount){
- // System.err.println("TIE BREAKKKEERRR " + count + ", " + maxCount);
- // return true;
- // }
- // if(maxCount < count) return false;
- return true;
- }
- }
- public class Lighting {
- String[] setLights(String[] mapStrings, int D, int L) {
- String[] ret = new String[L];
- // place L random valid lights
- Random r1;
- try {
- r1 = new Random();
- } catch (Exception e) { return ret; }
- r1.setSeed(123);
- int S = mapStrings.length;
- /*
- System.err.println("S = " + S);
- System.err.println("L = " + L);
- long maxScore = 0;
- P[] lights = new P[L];
- P[] maxLights = new P[L];
- int[] lightContrib = new int[L];
- int[] lightContribWoOverlap = new int[L];
- int[] maxLightContrib = new int[L];
- int[] maxLightContribWoOverlap = new int[L];
- ArrayList<Wall> walls = extractWalls(map);
- */
- final int NUM_SCENES = 2500/(S*S);
- final long MILLIS_TO_RUN = 19500;
- long startTime = System.currentTimeMillis();
- int tries = 0;
- boolean uppedres1 = false, uppedres2 = false;
- Map map = new Map(mapStrings, S, D, L);
- ArrayList<Scene> scenes = new ArrayList<Scene>();
- int nTotal;
- for(int i=0; i < NUM_SCENES; i++) {
- Scene scene = new Scene();
- //scene.init(map, S, D, L, 1);
- scene.init(map, S, D, L, 10000);
- for (int l = 0; l < L; ++l) {
- scene.moveLightToRand(r1, l);
- }
- scene.addLights();
- scenes.add(scene);
- }
- nTotal = scenes.get(0).getFloorPoints();
- int sceneNum = 0;
- while(true) {
- Scene scene = scenes.get(sceneNum);
- scene.illuminatedPoints();
- long curTime = System.currentTimeMillis();
- long millis = curTime - startTime;
- long millisLeft = MILLIS_TO_RUN - millis;
- if(millisLeft <=0) break;
- tries++;
- if(scene.score == nTotal) {
- for(Scene s: scenes) s.incSubdiv(200000);
- nTotal = scenes.get(0).getFloorPoints();
- scene.save();
- }
- // System.err.println("blah! #" + sceneNum + " score=" + scene.score);
- if(scene.score > scene.maxScore) {
- System.err.println("success! #" + sceneNum + " score=" + (scene.score*1.0/nTotal));
- scene.save();
- } else if(scene.score == scene.maxScore) {
- if(scene.tieBreakMax(r1)) {
- //System.err.println("TIE BREAKKKEERRR");
- //System.err.println("tie. #" + sceneNum + " score=" + (scene.score*1.0/nTotal));
- scene.save();
- } else {
- //System.err.println("Tie breaker fail");
- scene.restore();
- }
- } else {
- //System.err.println("worse #" + sceneNum + " score=" + (scene.score*1.0/nTotal));
- scene.restore();
- }
- // if(!uppedres1 && millisLeft <= 2000) {
- // uppedres1 = true;
- // for(Scene s: scenes) s.incSubdiv(100000);
- // nTotal = scenes.get(0).getFloorPoints();
- // }
- for(Scene s: scenes) s.incSubdiv((int)(millis * 2));
- nTotal = scenes.get(0).getFloorPoints();
- if(tries%10000 == 0 && scenes.size() > 1) {
- Scene minScene = null;
- long minScore = Long.MAX_VALUE;
- Scene maxScene = null;
- long maxScore = 0;
- int minSn = 0;
- for (int sn=0; sn < scenes.size(); sn++) {
- Scene s = scenes.get(sn);
- if(s.score < minScore) {
- minSn = sn;
- minScene = s;
- minScore = s.score;
- }
- if(s.score > maxScore) {
- maxScene = s;
- maxScore = s.score;
- }
- }
- if(maxScene != minScene) {
- for(int l=0; l < L; l++) {
- minScene.lights[l] = new P(maxScene.lights[l].x, maxScene.lights[l].y);
- }
- minScene.lights[r1.nextInt(L)] = minScene.randLight(r1);
- minScene.clearLights();
- minScene.addLights();
- minScene.maxScore = minScene.illuminatedPoints();
- //System.err.println("Fixing #" + minSn);
- }
- }
- // Remove worst one
- long m = Math.max(millisLeft-2000, 0);
- while(scenes.size() > (m / 1000)*(m / 1000)*(m/1000) + 1) {
- Scene minScene = null;
- long minScore = Long.MAX_VALUE;
- for (Scene s: scenes) {
- if(s.score < minScore) {
- minScene = s;
- minScore = s.score;
- }
- }
- scenes.remove(minScene);
- if(sceneNum >= scenes.size()) sceneNum = 0;
- }
- if(millis <= 10*1000) {
- int choice = r1.nextInt(10);
- //choice = 2;
- if(choice == 0) {
- // move least contrib light (counting overlap)
- int lightIdx = scene.getLeastContribLight();
- scene.moveLightToRand(r1, lightIdx);
- } else if(choice == -1) {
- // move least contrib light (not counting overlap)
- int lightIdx = scene.getLeastContribLightWoOverlap();
- scene.moveLightToRand(r1, lightIdx);
- } else {
- // move random light
- int lightIdx = r1.nextInt(L);
- scene.moveLightToRand(r1, lightIdx);
- }
- } else {
- // move random light a tiny amount
- //System.err.println("jiggling...");
- int lightIdx = r1.nextInt(L);
- long amtx=0, amty=0;
- while(true) {
- do {
- //amtx=(r1.nextInt(P.f*2/scene.subdiv + 1)-P.f/scene.subdiv)*2;
- //amty=(r1.nextInt(P.f*2/scene.subdiv + 1)-P.f/scene.subdiv)*2;
- long maxMove = P.f*2 * S / 2;
- //maxMove = maxMove * millisLeft / MILLIS_TO_RUN + 1;
- //maxMove = maxMove * millisLeft / MILLIS_TO_RUN * millisLeft / MILLIS_TO_RUN + 1;
- long m2 = millisLeft;
- maxMove = maxMove * m2 / MILLIS_TO_RUN * m2 / MILLIS_TO_RUN + 11;
- //System.err.println("maxmove=" + maxMove);
- //maxMove = (long) (maxMove * Math.exp((millisLeft-MILLIS_TO_RUN) / MILLIS_TO_RUN) + P.f*5);
- //System.err.println(maxMove + ", " + millisLeft);
- amtx=(r1.nextInt((int)maxMove*2 + 1) - maxMove)*2;
- amty=(r1.nextInt((int)maxMove*2 + 1) - maxMove)*2;
- } while(amtx==0 && amty==0);
- P newLight = new P(scene.lights[lightIdx].x + amtx, scene.lights[lightIdx].y + amty);
- if(!scene.isLightValid(newLight)) continue;
- scene.clearLight(lightIdx);
- scene.lights[lightIdx] = newLight;
- break;
- }
- scene.addLight(lightIdx);
- }
- sceneNum++;
- if(sceneNum >= scenes.size()) sceneNum = 0;
- }
- Scene scene = null;
- long maxScore = Long.MIN_VALUE;
- for(Scene s: scenes) {
- if(s.maxScore > maxScore) {
- scene = s;
- maxScore = s.maxScore;
- }
- }
- System.err.println("nTotal = " + nTotal);
- System.err.println("subdiv = " + scene.subdiv);
- System.err.println("tries = " + tries);
- for (int i = 0; i < L; ++i) {
- long xw = scene.maxLights[i].x/(2*P.f);
- long xdec = (scene.maxLights[i].x%(2*P.f))/2;
- long yw = scene.maxLights[i].y/(2*P.f);
- long ydec = (scene.maxLights[i].y%(2*P.f))/2;
- ret[i] = String.format("%d.%02d %d.%02d", xw, xdec, yw, ydec);
- System.err.println("final: " + ret[i]);
- }
- System.err.println("estim = " + (maxScore * 1.0 / nTotal));
- return ret;
- }
- // -------8<------- end of solution submitted to the website -------8<-------
- public static void main(String[] args) {
- try {
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- int S = Integer.parseInt(br.readLine());
- String[] map = new String[S];
- for (int i = 0; i < S; ++i) {
- map[i] = br.readLine();
- }
- int D = Integer.parseInt(br.readLine());
- int L = Integer.parseInt(br.readLine());
- Lighting l = new Lighting();
- String[] ret = l.setLights(map, D, L);
- System.out.println(ret.length);
- for (int i = 0; i < ret.length; ++i) {
- System.out.println(ret[i]);
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement