AtCoder Beginner Contest 223 E - Placing Rectangles(思维)

E - Placing Rectangles

题目大意:

给你一个 \(X \times Y\) 的矩形,问你能不能塞入三个不重叠的面积分别大于等于 \(A, B, C\) 的矩形

思路:

首先能够想到贪心的思路,优先处理面积最大的矩形,再在剩余的区域内处理面积次大的矩形。但是这样就陷入了繁琐的分类讨论之中。

此时我们可以考虑类似数学归纳法的思想,先处理问题规模较小时候的情况,看能不能推广到问题规模增大后的情况。

在这里,我们需要给三个矩形分配位置,那么我们首先考虑给两个矩形分配位置的情况。

设两个矩形的面积分别至少为 \(A\)\(B\)

对于所有合法的位置,一定存在一条平行于 \(x\) 轴或 \(y\) 轴的直线 \(l\),且 \(l\) 满足:

  • 不会穿过任何一个矩形的内部
  • 将整块区域划分为两部分,每一部分正好能够放置一个矩形

如果该直线 \(l\) 存在,且与 \(x\) 轴平行,则 \(l\) 的取值为 \(y=\left\lceil\frac{S}{X}\right\rceil\),然后在剩余的区域内再做划分。平行 \(y\) 轴同理。

不难看出,当题目要求需要划分三个矩形时,我们可以先划分出一个矩形,转化成两个矩形时的情况。

考虑使用 dfs 求解,可以推广到划分 \(n\) 个矩形的情况。

Code:
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    ll x, y;
    vector<ll> s(3);
    cin >> x >> y;
    for (auto &i : s) {
        cin >> i;
    }
    
    auto sol = [&](auto self, ll x, ll y, int id) {
        if (id == 3) {
            return true;
        }
        if (x == 0 || y == 0) {
            return false;
        }
        bool ok = false;

        ll t1 = (s[id] + y - 1) / y;
        if (t1 <= x) {
            ok |= self(self, x - t1, y, id + 1);
        }
         
        ll t2 = (s[id] + x - 1) / x;
        if (t2 <= y) {
            ok |= self(self, x, y - t2, id + 1);
        }
        return ok;
    };

    bool gok = false;
    sort(s.begin(), s.end());
    do {
        gok |= sol(sol, x, y, 0);
    } while (next_permutation(s.begin(), s.end()));
    cout << (gok ? "Yes" : "No") << "\n";
    
    return 0;
}
posted @ 2022-02-26 13:23  Nepenthe8  阅读(72)  评论(0编辑  收藏  举报