Once upon a time there was a greedy King who ordered his chief Architect to build a field for royal cricket inside his park. The King was so greedy, that he would not listen to his Architect's proposals to build a field right in the park center with pleasant patterns of trees specially planted around and beautiful walks inside tree alleys for spectators. Instead, he ordered neither to cut nor to plant even a single tree in his park, but demanded to build the largest possible cricket field for his pleasure. If the Kind finds that the Architect has dared to touch even a single tree in his park or designed a smaller field that it was possible, then the Architect will loose his head. Moreover, he demanded his Architect to introduce at once a plan of the field with its exact location and size.
Your task is to help poor Architect to save his head, by writing a program that will find the maximum possible size of the cricket field and its location inside the park to satisfy King's requirements.
The task is somewhat simplified by the fact, that King's park has a rectangular shape and is situated on a flat ground. Moreover, park's borders are perfectly aligned with North-South and East-West lines. At the same time, royal cricket is always played on a square field that is also aligned with North-South and East-West lines. Architect has already established a Cartesian coordinate system and has precisely measured the coordinates of every tree. This coordinate system is, of course, aligned with North-South and East-West lines. Southwestern corner of the park has coordinates (0, 0) and Northeastern corner of the part has coordinates (W, H), where W and H are the park width and height in feet respectively.
For this task, you may neglect the diameter of the trees. Trees cannot be inside the cricket field, but may be situated on its side. The cricket field may also touch park's border, but shall not lie outside the park.
Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.
The first line of the input file contains three integer numbers N, W, and H, separated by spaces. N ( 0N100) is the number of trees in the park. W and H ( 1W, H10000) are the park width and height in feet respectively.
Next N lines describe coordinates of trees in the park. Each line contains two integer numbers Xi and Yiseparated by a space ( 0XiW, 0YiH) that represent coordinates of i-th tree. All trees are located at different coordinates.
Output
For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.
Write to the output file a single line with three integer numbers P, Q, and L separated by spaces, where (P,Q) are coordinates of the cricket field Southwestern corner, and L is a length of its sides. If there are multiple possible field locations with a maximum size, then output any one.
Sample Input
1 7 10 7 3 2 4 2 7 0 7 3 4 5 2 4 1 7
Sample Output
4 3 4
题意:n个点,在w*h平面上,求最大正方形,内部不包含点。
思路:其实说是找正方形,等同于找矩形,只是输出的时候是输出矩形的较短边,先把左右边界离散化,然后枚举左右边界,从下往上推上下边界,类似这题:UVA 1382 Distant Galaxy
然后在网上看到的一种比较巧妙的方法,就是一开始一块矩形,然后每次加进每个点的时候,如果点在矩形内,就可以把矩形分割为4个矩形,然后最后在所有分割完的矩形中去枚举出最大的符合条件即可。不过跑起来比较久。
代码一:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int MAXN = 10005;
const int N = 105;
int t, n, w, h, vis[MAXN], xn, X[MAXN];
struct Point {
int x, y;
} p[N];
bool cmpx(Point a, Point b) {
return a.x < b.x;
}
bool cmpy(Point a, Point b) {
return a.y < b.y;
}
void init() {
xn = 0;
memset(vis, 0, sizeof(vis));
vis[0] = 1;
X[xn++] = 0;
scanf("%d%d%d", &n, &w, &h);
for (int i = 0; i < n; i++)
scanf("%d%d", &p[i].x, &p[i].y);
sort(p, p + n, cmpx);
for (int j = 0; j < n; j++) {
if (!vis[p[j].x]) {
vis[p[j].x] = 1;
X[xn++] = p[j].x;
}
}
if (!vis[w])
X[xn++] = w;
}
void solve() {
int ansx, ansy, Max = 0;
sort(p, p + n, cmpy);
for (int i = 0; i < xn; i++)
for (int j = i + 1; j < xn; j++) {
int down = 0;
int ww = X[j] - X[i];
for (int k = 0; k < n; k++) {
if (p[k].x <= X[i] || p[k].x >= X[j]) continue;
int hh = p[k].y - down;
if (Max < min(ww, hh)) {
Max = min(ww, hh);
ansx = X[i]; ansy = down;
}
down = p[k].y;
}
int hh = h - down;
if (Max < min(ww, hh)) {
Max = min(ww, hh);
ansx = X[i]; ansy = down;
}
}
printf("%d %d %d\n", ansx, ansy, Max);
}
int main() {
scanf("%d", &t);
while (t--) {
init();
solve();
if (t) printf("\n");
}
return 0;
}
代码二:
#include <stdio.h>
#include <string.h>
#include <queue>
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N = 105;
int t, n, w, h;
struct Point{
int x, y;
Point(){}
Point(int xx, int yy) {
x = xx; y = yy;
}
} p[N];
struct SQU{
Point a, b, c, d;
SQU(){}
SQU(Point aa, Point bb, Point cc, Point dd) {
a = aa; b = bb; c = cc; d = dd;
}
int H() {
return a.y - d.y;
}
int W() {
return b.x - a.x;
}
};
queue<SQU> Q;
bool in_judge(SQU s, Point e) {
if (e.x > s.a.x && e.x < s.b.x && e.y < s.a.y && e.y > s.c.y) return true;
return false;
}
void init() {
scanf("%d%d%d", &n, &w, &h);
Q.push(SQU(Point(0, h), Point(w, h), Point(w, 0), Point(0, 0)));
for (int i = 0; i < n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
}
}
void solve() {
for (int i = 0; i < n; i++) {
int sz = Q.size();
for (int j = 0; j < sz; j++) {
SQU save = Q.front();
Q.pop();
if (in_judge(save, p[i])) {
Point aa = Point(p[i].x, save.a.y);
Point bb = Point(save.b.x, p[i].y);
Point cc = Point(p[i].x, save.c.y);
Point dd = Point(save.a.x, p[i].y);
Q.push(SQU(save.a, save.b, bb, dd));
Q.push(SQU(dd, bb, save.c, save.d));
Q.push(SQU(save.a, aa, cc, save.d));
Q.push(SQU(aa, save.b, save.c, cc));
}
else Q.push(save);
}
}
Point ansp; int Max = 0;
while (!Q.empty()) {
SQU save = Q.front();
Q.pop();
int t = min(save.H(), save.W());
if (Max < t) {
Max = t;
ansp.x = save.d.x; ansp.y = save.d.y;
}
}
printf("%d %d %d\n", ansp.x, ansp.y, Max);
}
int main() {
scanf("%d", &t);
while (t--) {
init();
solve();
if (t) printf("\n");
}
return 0;
}