1312 - Cricket Field

该题的网格大小非常大,看似需要离散化,但是实际上是不需要的 。  因为我们可以发现,既然要求正方形里没有树,我们不妨直接枚举树就可以了 。 所以我们将纵坐标单独拿出来从小到大排序,二重循环就可以枚举出矩形上下界,然后关键是横坐标的枚举。 同样,我们将横坐标排序,然后判断对应的纵坐标是否在上下界范围内,通过观察,如果不在,那么这个点将不在当前枚举的矩形中,所以直接跳过就可以了,这样的话,我们只需要一个变量来动态维护左边界就可以了 。

细节 参见代码:

#include<bits/stdc++.h>
using namespace std;
int T,n,w,h,y[105],len;
struct point{
    int x,y;
}a[105];
bool cmp(point a,point b) {
    return a.x < b.x || (a.x == b.x && a.y < b.y);
}
void solve() {
    sort(a,a+n,cmp);
    sort(y,y+n+2);
    len = unique(y,y+n+2) - y; //只是减少一点复杂度
    int ansx,ansy,ans = -1,hh,ww;
    for(int i=0;i<len;i++) {
        for(int j=i+1;j<len;j++) {
            hh = y[j] - y[i]; //矩形的高度
            int cur_x = 0;
            for(int k=0;k<n;k++) {
                if((a[k].y <= y[i] || a[k].y >= y[j])) continue;
                ww = a[k].x - cur_x; //矩形的宽度
                ww = min(ww,hh); //取最大正方形
                if(ans < ww) {
                    ansx = cur_x; ansy = y[i]; ans = ww;
                }
                cur_x = a[k].x;
            }
            ww = w - cur_x;
            ww = min(ww,hh);
            if(ans < ww) {
                ansx = cur_x; ansy = y[i]; ans = ww;
            }
        }
    }
    printf("%d %d %d\n",ansx,ansy,ans);
    if(T) printf("\n");
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d%d",&n,&w,&h);
        for(int i=0;i<n;i++) { scanf("%d%d",&a[i].x,&a[i].y); y[i] = a[i].y; }
        y[n] = 0; y[n+1] = h; //添加边界值,重复也没有关系,还要去重
        solve();
    }
    return 0;
}


你可能感兴趣的:(ACM,uva)