UVA-1312 Cricket Field (技巧枚举)

题目大意:在一个w*h的网格中,有n个点,找出一个最大的正方形,使得正方形内部没有点。

题目分析:寻找正方形实质上等同于寻找矩形(只需令长宽同取较短的边长)。那么枚举出所有可能的长宽组合取最优答案即可,如何枚举长宽组合呢?通过两重循环枚举纵坐标来确定矩形的一条边长,枚举点的横坐标来完成对另一条边长的枚举。这样一来,就可以把所有的矩形都枚举遍。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;

struct XY
{
    int x,y;
    bool operator < (const XY &a) const {
        if(x==a.x)
            return y<a.y;
        return x<a.x;
    }
};
XY xy[105];
int d[105],n,w,h;

void solve()
{
    sort(xy+1,xy+n+1);
    sort(d,d+n+2);
    int ans=0,ansx,ansy;
    for(int i=0;i<=n+1;++i){
        for(int j=i+1;j<=n+1;++j){
            int high=d[j],low=d[i],temp=0,r=d[j]-d[i],c;
            for(int k=1;k<=n;++k){
                if(xy[k].y<=low||xy[k].y>=high)
                    continue;
                c=xy[k].x-temp;
                if(ans<min(r,c)){
                    ans=min(r,c);
                    ansx=temp,ansy=low;
                }
                temp=xy[k].x;
            }
            c=w-temp;
            if(ans<min(r,c)){
                ans=min(r,c);
                ansx=temp,ansy=low;
            }
        }
    }
    printf("%d %d %d
",ansx,ansy,ans);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&w,&h);
        d[0]=0,d[n+1]=h;
        for(int i=1;i<=n;++i){
            scanf("%d%d",&xy[i].x,&xy[i].y);
            d[i]=xy[i].y;
        }
        solve();
        if(T)
            printf("
");
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/4889518.html