[枚举] 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。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
类型是一个有限的取值集合,可以通过序列和反序列将其转换为字符串或数字。 序列:将枚类型转换为字符串或数字,以便于存储或传输。在C#中,可以使用Enum.ToString()方法将枚转换为字符串,也可以使用(Enum)枚值将枚转换为整数。 反序列:将字符串或数字转换为枚类型。在C#中,可以使用Enum.Parse()方法将字符串转换为枚类型,也可以使用(Enum)整数将整数转换为枚类型。 以下是一个示代码: ```csharp using System; enum DayOfWeek { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } class Program { static void Main(string[] args) { // 序列 DayOfWeek day = DayOfWeek.Monday; string dayStr = day.ToString(); int dayInt = (int)day; Console.WriteLine($"dayStr: {dayStr}"); Console.WriteLine($"dayInt: {dayInt}"); // 反序列 string dayStr2 = "Wednesday"; DayOfWeek day2 = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), dayStr2); int dayInt2 = 5; DayOfWeek day3 = (DayOfWeek)dayInt2; Console.WriteLine($"day2: {day2}"); Console.WriteLine($"day3: {day3}"); } } ``` 输出结果: ``` dayStr: Monday dayInt: 1 day2: Wednesday day3: Friday ``` 在上面的示中,我们首先将枚类型`DayOfWeek`的值序列为字符串和整数,然后将其反序列为枚类型的值。注意,反序列时需要使用`Enum.Parse()`方法将字符串转换为枚类型,或者使用强制类型转换将整数转换为枚类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值