[枚举] UVa1312 球场 (离散化)(技巧枚举典例)

题目

这里写图片描述
这里写图片描述

思路

本题的关键就在于枚举的技巧和离散化。
1.离散化:对于一个最大的正方形,其必然至少有两条边上有点,因为没有的话还可以继续扩展。这样就直接将题目给的10000x10000的数据范围离散到了100个树。
2.技巧枚举:枚举正方形对边而不是起始点和边长。首先枚举上边和下边,最后枚举左边和右边。注意枚举左边和右边时,只需在已找到上边下边范围内,找黑点作为分隔符,随后分割成几部分就有几个矩形。这里写图片描述

3.对于技巧枚举的总结:通过先枚举和部分枚举,原则:
①可由已枚举量得未枚举量。
②部分枚举的量由题设限制,降低了枚举量。

代码

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <set>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
using namespace std;

const int maxn = 10000 + 100;
struct Point {
    int x, y;
}A[maxn];

int n, W, H;

int main() {

    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d%d", &n, &W, &H);
        _for(i, 0, n) scanf("%d%d", &A[i].x, &A[i].y);

        int ans = 0, ansx, ansy;
        set<int> ycand;  // 去重排序的y坐标集合,用于确定上下边 
        _for(i, 0, n) ycand.insert(A[i].y);
        ycand.insert(0); ycand.insert(H);

        for (set<int>::iterator ledge = ycand.begin(); ledge != ycand.end(); ++ledge)  // 下面的边
            for (set<int>::iterator hedge = ledge; hedge != ycand.end(); ++hedge) {  // 上面的边
                if (ledge == hedge) ++hedge;
                if (hedge == ycand.end()) break;
                set<int> xcand;  // 去重排序x坐标集合,用于确定左右边
                _for(i, 0, n)
                    if (A[i].y < *hedge && A[i].y > *ledge) {
                        xcand.insert(A[i].x);
                    }
                xcand.insert(0); xcand.insert(W);

                set<int>::iterator lastone = xcand.end(); --lastone;
                for (set<int>::iterator xledge = xcand.begin(); xledge != lastone; ++xledge) {
                    set<int>::iterator xredge = xledge;
                    ++xredge;
                    int heng = abs(*xledge - *xredge), shu = abs(*hedge - *ledge);
                    int len = min(heng, shu);
                    if (len > ans) {
                        ans = len;
                        ansx = *xledge;
                        ansy = *ledge;
                    }
                }
            }
        printf("%d %d %d\n", ansx, ansy, ans);
        if (T) printf("\n");
    }

    return 0;
}

废话

气死了,写完了忘删freopen,上去提交WA,然后还写了个对拍,折腾了将近半个多小时,最后才发现仅仅是没删freopen。

阅读更多
文章标签: 枚举 离散化
上一篇[预处理] UVa1619 感觉不错 (单调栈)(预处理典例)
下一篇[枚举] UVa1618 弱键 (预处理)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭