ABC 223 | E - Placing Rectangles

题目描述

给定\(X, Y, A, B, C\),问能否在\(0 \le x \le X, 0 \le y \le Y\)的范围中不相重叠地放置面积为\(A, B, C\)的三个矩形。

数据范围

  • \(1 \le X, Y \le 10^9\)
  • \(1 \le A, B, C \le 10^{18}\)

解题思路

  • 首先考虑放置两个矩形的情况:
    必存在一条平行于\(x\)轴或\(y\)轴的直线\(l\)\(l\)满足以下条件:

    • \(l\)穿过任何一个矩形内部
    • \(l\)将平面区域分为两部分,每个部分各有一个矩形

    因此可以暴搜\(l\)\(x\)\(y\)轴平行以及两个矩形各自的位置,判断能否不相重叠地放置两个矩形。
    注意此处不是枚举\(l\)的位置,而是首先填充一个矩形,再填充另一个矩形,借此隐性地枚举\(l\)

  • 下面考虑放置三个矩形的情况:
    必存在一条平行于\(x\)轴或\(y\)轴的直线\(l\)\(l\)满足以下条件:

    • \(l\)不穿过任何一个矩形内部
    • \(l\)将平面区域分为两部分,一个区域含有一个矩形,另一个区域中含有两个矩形

    因此可以暴搜\(l\)\(x\)\(y\)轴平行以及三个矩形的摆放情况。此处可以首先枚举一个矩形的位置,然后再剩余区域内按照放置两个矩形的方法来判断。

  • 关于代码撰写:
    在学习代码的过程中,发先了一个很好的暴搜方法。for循环枚举情况属,通过swap方法进行暴搜,代码简洁。有示例如下:

bool solve3(ll x, ll y, ll a, ll b, ll c)
{
    for(int i = 0; i < 2; i ++){
        for(int j = 0; j < 3; j ++){
            ll len = (a - 1) / x + 1;
            if(len < y && solve2(x, y - len, b, c)){
                return true;
            }
            swap(a, b);
            swap(b, c);
        }
        swap(x, y);
    }
    return false;
}

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

ll x, y, a, b, c;

bool solve2(ll x, ll y, ll a, ll b)
{
    for(int i = 0; i < 2; i ++){
        ll len = (a - 1) / x + 1;
        if(len < y && x * (y - len) >= b) return true;
        swap(x, y);
    }
    return false;
}

bool solve3(ll x, ll y, ll a, ll b, ll c)
{
    for(int i = 0; i < 2; i ++){
        for(int j = 0; j < 3; j ++){
            ll len = (a - 1) / x + 1;
            if(len < y && solve2(x, y - len, b, c)){
                return true;
            }
            swap(a, b);
            swap(b, c);
        }
        swap(x, y);
    }
    return false;
}

int main()
{
    scanf("%lld%lld%lld%lld%lld", &x, &y, &a, &b, &c);
    if(solve3(x, y, a, b, c)) puts("Yes");
    else puts("No");
    return 0;
}

posted @ 2022-06-16 15:28  小菜珠的成长之路  阅读(95)  评论(0)    收藏  举报