import javax.swing.*;
import java.awt.*;
import java.awt.geom.Point2D;
import java.util.*;
import java.util.List;
public class Main {
public static void main
(String[] args
) { int N = 20;
int K = 4;
// generate points
List<Point2D> points = new ArrayList<Point2D>();
for (int i = 0; i < N; ++i) {
points.
add(new Point2D.
Double(rnd.
nextInt(100), rnd.
nextInt(100))); }
// sort points by X
List<Point2D> sortedX = new ArrayList<Point2D>(points);
@Override
return Double.
compare(o1.
getX(), o2.
getX()); }
});
// sort points by Y
List<Point2D> sortedY = new ArrayList<Point2D>(points);
@Override
return Double.
compare(o1.
getY(), o2.
getY()); }
});
// iterate through all combinations of left and bottom edges
for (int i = 0; i < N - K + 1; ++i) {
for (int j = 0; j < N - K + 1; ++j) {
Point2D leftPoint
= sortedX.
get(i
); Point2D bottomPoint
= sortedY.
get(j
); if (leftPoint.getX() > bottomPoint.getX() || leftPoint.getY() < bottomPoint.getY()) {
continue;
}
int leftEdge = (int) leftPoint.getX() - 1;
int bottomEdge = (int) bottomPoint.getY() - 1;
// get points that are above and to the right of the corner
Set<Point2D> acceptablePoints = new HashSet<Point2D>(sortedX.subList(i, N));
acceptablePoints.retainAll(new HashSet<Point2D>(sortedY.subList(j, N)));
if (acceptablePoints.size() < K) {
continue; // not enough points
}
// calculate and sort areas
List<Integer> areas = new ArrayList<Integer>();
for (Point2D point
: acceptablePoints
) { int squareSide
= (int) Math.
max(point.
getX() + 1 - leftEdge, point.
getY() + 1 - bottomEdge
); areas.add(squareSide * squareSide);
}
// update minArea
int currentArea = areas.get(K - 1);
if (minArea > currentArea) {
minArea = currentArea;
corner
= new Point2D.
Float(leftEdge, bottomEdge
); // for debug only }
}
}
System.
out.
println("Min area: " + minArea
); // drawSquare(points, corner, minArea); // uncomment me
}
public static void drawSquare
(final List
<Point2D
> points,
final Point2D sqCorner,
final int minArea
) { final int s = 6;
jFrame.setSize(100 * s, 100 * s);
jFrame.setResizable(false);
@Override
g.fillRect(0, 0, getWidth(), getHeight());
int side
= (int) Math.
sqrt(minArea
); g.fillRect((int) sqCorner.getX() * s - 2, (int) sqCorner.getY() * s - 2, side * s + 4, side * s + 4);
g.fillOval((int) point.getX() * s - 2, (int) point.getY() * s - 2, 4, 4);
}
}
});
jFrame.setVisible(true);
}
}
aW1wb3J0IGphdmF4LnN3aW5nLio7CmltcG9ydCBqYXZhLmF3dC4qOwppbXBvcnQgamF2YS5hd3QuZ2VvbS5Qb2ludDJEOwppbXBvcnQgamF2YS51dGlsLio7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKCnB1YmxpYyBjbGFzcyBNYWluIHsKCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CiAgICAgICAgaW50IE4gPSAyMDsKICAgICAgICBpbnQgSyA9IDQ7CiAgICAgICAgaW50IG1pbkFyZWEgPSBJbnRlZ2VyLk1BWF9WQUxVRTsKCiAgICAgICAgLy8gZ2VuZXJhdGUgcG9pbnRzCiAgICAgICAgTGlzdDxQb2ludDJEPiBwb2ludHMgPSBuZXcgQXJyYXlMaXN0PFBvaW50MkQ+KCk7CiAgICAgICAgUmFuZG9tIHJuZCA9IG5ldyBSYW5kb20oMSk7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyArK2kpIHsKICAgICAgICAgICAgcG9pbnRzLmFkZChuZXcgUG9pbnQyRC5Eb3VibGUocm5kLm5leHRJbnQoMTAwKSwgcm5kLm5leHRJbnQoMTAwKSkpOwogICAgICAgIH0KCiAgICAgICAgLy8gc29ydCBwb2ludHMgYnkgWAogICAgICAgIExpc3Q8UG9pbnQyRD4gc29ydGVkWCA9IG5ldyBBcnJheUxpc3Q8UG9pbnQyRD4ocG9pbnRzKTsKICAgICAgICBDb2xsZWN0aW9ucy5zb3J0KHNvcnRlZFgsIG5ldyBDb21wYXJhdG9yPFBvaW50MkQ+KCkgewogICAgICAgICAgICBAT3ZlcnJpZGUKICAgICAgICAgICAgcHVibGljIGludCBjb21wYXJlKFBvaW50MkQgbzEsIFBvaW50MkQgbzIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBEb3VibGUuY29tcGFyZShvMS5nZXRYKCksIG8yLmdldFgoKSk7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKCiAgICAgICAgLy8gc29ydCBwb2ludHMgYnkgWQogICAgICAgIExpc3Q8UG9pbnQyRD4gc29ydGVkWSA9IG5ldyBBcnJheUxpc3Q8UG9pbnQyRD4ocG9pbnRzKTsKICAgICAgICBDb2xsZWN0aW9ucy5zb3J0KHNvcnRlZFksIG5ldyBDb21wYXJhdG9yPFBvaW50MkQ+KCkgewogICAgICAgICAgICBAT3ZlcnJpZGUKICAgICAgICAgICAgcHVibGljIGludCBjb21wYXJlKFBvaW50MkQgbzEsIFBvaW50MkQgbzIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBEb3VibGUuY29tcGFyZShvMS5nZXRZKCksIG8yLmdldFkoKSk7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKCiAgICAgICAgLy8gaXRlcmF0ZSB0aHJvdWdoIGFsbCBjb21iaW5hdGlvbnMgb2YgbGVmdCBhbmQgYm90dG9tIGVkZ2VzCiAgICAgICAgUG9pbnQyRCBjb3JuZXIgPSBudWxsOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTiAtIEsgKyAxOyArK2kpIHsKICAgICAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBOIC0gSyArIDE7ICsraikgewogICAgICAgICAgICAgICAgUG9pbnQyRCBsZWZ0UG9pbnQgPSBzb3J0ZWRYLmdldChpKTsKICAgICAgICAgICAgICAgIFBvaW50MkQgYm90dG9tUG9pbnQgPSBzb3J0ZWRZLmdldChqKTsKICAgICAgICAgICAgICAgIGlmIChsZWZ0UG9pbnQuZ2V0WCgpID4gYm90dG9tUG9pbnQuZ2V0WCgpIHx8IGxlZnRQb2ludC5nZXRZKCkgPCBib3R0b21Qb2ludC5nZXRZKCkpIHsKICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGludCBsZWZ0RWRnZSA9IChpbnQpIGxlZnRQb2ludC5nZXRYKCkgLSAxOwogICAgICAgICAgICAgICAgaW50IGJvdHRvbUVkZ2UgPSAoaW50KSBib3R0b21Qb2ludC5nZXRZKCkgLSAxOwogICAgICAgICAgICAgICAgLy8gZ2V0IHBvaW50cyB0aGF0IGFyZSBhYm92ZSBhbmQgdG8gdGhlIHJpZ2h0IG9mIHRoZSBjb3JuZXIKICAgICAgICAgICAgICAgIFNldDxQb2ludDJEPiBhY2NlcHRhYmxlUG9pbnRzID0gbmV3IEhhc2hTZXQ8UG9pbnQyRD4oc29ydGVkWC5zdWJMaXN0KGksIE4pKTsKICAgICAgICAgICAgICAgIGFjY2VwdGFibGVQb2ludHMucmV0YWluQWxsKG5ldyBIYXNoU2V0PFBvaW50MkQ+KHNvcnRlZFkuc3ViTGlzdChqLCBOKSkpOwogICAgICAgICAgICAgICAgaWYgKGFjY2VwdGFibGVQb2ludHMuc2l6ZSgpIDwgSykgewogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBub3QgZW5vdWdoIHBvaW50cwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gY2FsY3VsYXRlIGFuZCBzb3J0IGFyZWFzCiAgICAgICAgICAgICAgICBMaXN0PEludGVnZXI+IGFyZWFzID0gbmV3IEFycmF5TGlzdDxJbnRlZ2VyPigpOwogICAgICAgICAgICAgICAgZm9yIChQb2ludDJEIHBvaW50IDogYWNjZXB0YWJsZVBvaW50cykgewogICAgICAgICAgICAgICAgICAgIGludCBzcXVhcmVTaWRlID0gKGludCkgTWF0aC5tYXgocG9pbnQuZ2V0WCgpICsgMSAtIGxlZnRFZGdlLCBwb2ludC5nZXRZKCkgKyAxIC0gYm90dG9tRWRnZSk7CiAgICAgICAgICAgICAgICAgICAgYXJlYXMuYWRkKHNxdWFyZVNpZGUgKiBzcXVhcmVTaWRlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIENvbGxlY3Rpb25zLnNvcnQoYXJlYXMpOwogICAgICAgICAgICAgICAgLy8gdXBkYXRlIG1pbkFyZWEKICAgICAgICAgICAgICAgIGludCBjdXJyZW50QXJlYSA9IGFyZWFzLmdldChLIC0gMSk7CiAgICAgICAgICAgICAgICBpZiAobWluQXJlYSA+IGN1cnJlbnRBcmVhKSB7CiAgICAgICAgICAgICAgICAgICAgbWluQXJlYSA9IGN1cnJlbnRBcmVhOwogICAgICAgICAgICAgICAgICAgIGNvcm5lciA9IG5ldyBQb2ludDJELkZsb2F0KGxlZnRFZGdlLCBib3R0b21FZGdlKTsgLy8gZm9yIGRlYnVnIG9ubHkKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIk1pbiBhcmVhOiAiICsgbWluQXJlYSk7CiAgICAgICAgLy8gZHJhd1NxdWFyZShwb2ludHMsIGNvcm5lciwgbWluQXJlYSk7IC8vIHVuY29tbWVudCBtZQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBkcmF3U3F1YXJlKGZpbmFsIExpc3Q8UG9pbnQyRD4gcG9pbnRzLCBmaW5hbCBQb2ludDJEIHNxQ29ybmVyLCBmaW5hbCBpbnQgbWluQXJlYSkgewogICAgICAgIEpGcmFtZSBqRnJhbWUgPSBuZXcgSkZyYW1lKCJTcXVhcmVzIik7CiAgICAgICAgakZyYW1lLnNldERlZmF1bHRDbG9zZU9wZXJhdGlvbihXaW5kb3dDb25zdGFudHMuRVhJVF9PTl9DTE9TRSk7CiAgICAgICAgZmluYWwgaW50IHMgPSA2OwogICAgICAgIGpGcmFtZS5zZXRTaXplKDEwMCAqIHMsIDEwMCAqIHMpOwogICAgICAgIGpGcmFtZS5zZXRSZXNpemFibGUoZmFsc2UpOwogICAgICAgIGpGcmFtZS5hZGQobmV3IEpQYW5lbCgpIHsKICAgICAgICAgICAgQE92ZXJyaWRlCiAgICAgICAgICAgIHB1YmxpYyB2b2lkIHBhaW50KEdyYXBoaWNzIGcpIHsKICAgICAgICAgICAgICAgIGcuc2V0Q29sb3IoQ29sb3IuV0hJVEUpOwogICAgICAgICAgICAgICAgZy5maWxsUmVjdCgwLCAwLCBnZXRXaWR0aCgpLCBnZXRIZWlnaHQoKSk7CiAgICAgICAgICAgICAgICBnLnNldENvbG9yKENvbG9yLkdSQVkpOwogICAgICAgICAgICAgICAgaW50IHNpZGUgPSAoaW50KSBNYXRoLnNxcnQobWluQXJlYSk7CiAgICAgICAgICAgICAgICBnLmZpbGxSZWN0KChpbnQpIHNxQ29ybmVyLmdldFgoKSAqIHMgLSAyLCAoaW50KSBzcUNvcm5lci5nZXRZKCkgKiBzIC0gMiwgc2lkZSAqIHMgKyA0LCBzaWRlICogcyArIDQpOwogICAgICAgICAgICAgICAgZy5zZXRDb2xvcihDb2xvci5CTEFDSyk7CiAgICAgICAgICAgICAgICBmb3IgKFBvaW50MkQgcG9pbnQgOiBwb2ludHMpIHsKICAgICAgICAgICAgICAgICAgICBnLmZpbGxPdmFsKChpbnQpIHBvaW50LmdldFgoKSAqIHMgLSAyLCAoaW50KSBwb2ludC5nZXRZKCkgKiBzIC0gMiwgNCwgNCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICBqRnJhbWUuc2V0VmlzaWJsZSh0cnVlKTsKICAgIH0KfQo=