1 条题解
-
0
A. 矩形的正方形 题解
题目理解
给定三个矩形,尺寸分别为 、、,满足:
要求判断是否能将这三个矩形拼成一个正方形,要求:
- 矩形不能旋转(即长和宽不能互换)
- 矩形边与正方形边平行
- 矩形之间不能重叠
解题思路
由于矩形不能旋转,且边长已经按从大到小排序,我们可以枚举所有可能的拼接方式。
核心观察
三个矩形拼成正方形,只有两种基本布局方式:
布局一:三个矩形并排放置(长度方向一致)
此时正方形的边长等于最长矩形的长,三个矩形的宽之和等于正方形边长。布局二:两个矩形并排放,第三个矩形放在它们上面(或下面)
此时需要满足宽度和高度的匹配关系。
详细分析
情况1:三个矩形的长都相等
设
此时有两种子情况:
子情况1.1:三个矩形并排放
正方形的边长
三个矩形的宽之和 必须等于
即:子情况1.2:两个矩形并排放,第三个矩形放在它们上面
设正方形边长为- 下面两个矩形并排放,它们的长之和必须等于 ,且它们的高相等(都为 ?需要仔细分析)
实际上,在这种布局中:
- 由于 ,如果两个矩形并排放,它们的宽度方向(即 方向)会成为正方形的高
- 正方形边长 ?等等,这不对
正确分析:因为所有矩形的长都是 ,所以:
- 如果两个矩形并排放(比如矩形2和矩形3),它们的长 会成为正方形的高
- 第三个矩形(矩形1)放在它们旁边或上面
- 实际上可行的布局是:矩形1竖着放(高 ,宽 ),矩形2和矩形3横着并排放在矩形1旁边(它们的高 和 ,但需要 才能并排放)
等等,这样分析很乱。让我们系统化:
正确解法:由于标程已经给出了简洁的判断逻辑,我们来解读它。
标程逻辑解读
标程的核心判断函数
check():auto check = [&] () { if (l1 == l2 && l2 == l3) return (l1 == b1 + b2 + b3 || (b1 == b2 + b3 && 2*l1 == b1)); if (l2 == l3) return (b2 + b3 == b1 && b1 == l2 + l1); return false; };情况1:
此时三个矩形的长度相等,设为 。
子情况1.1:三个矩形并排放
正方形边长
三个矩形宽度之和
条件:子情况1.2:两个矩形并排放,第三个放在它们上面
此时,两个宽度较小的矩形( 和 )并排放,放在下面,它们的宽度之和 作为正方形的边长;上面的矩形()横跨整个宽度,但注意:上面的矩形长度方向是 ,所以它的长度会成为正方形的高度。更准确地说:
- 下面两个矩形并排放,它们的高度都是 (因为长度方向作为高度),宽度分别是 和 ,总宽度
- 上面一个矩形横着放,它的宽度 ,高度
- 正方形边长 (上面矩形的宽度必须等于下面总宽度)
- 同时,正方形的高度 ?不对,下面矩形高度是 ,上面矩形高度也是 ,总高度
实际上,这种布局是:下面两个矩形并排放(它们的高都是 ,宽分别是 、),上面一个矩形(高 ,宽 )放在它们上面。
总宽度 ,总高度
要形成正方形,需要:
且 ?但条件写的是 且所以条件: 且
情况2:(但 可能不同)
此时矩形2和矩形3的长度相等。
可行布局:矩形1和矩形2、3中的一个并排放,另一个放在上面
具体来说,标程判断的条件是:
这意味着:
- 矩形1的宽度 等于矩形2和矩形3的宽度之和
- 矩形1的宽度也等于
这种布局的解释:
- 矩形2和矩形3并排放(它们的高度都是 ,因为长度方向作为高度)
- 矩形1放在它们旁边(竖着放,高度 ,宽度 )
- 总高度 (矩形1的高度)需要等于 (矩形2、3的高度)?这不对
实际上正确的几何解释:
- 矩形2和矩形3并排放,它们的高度都是 (长度方向),宽度分别是 和 ,总宽度
- 矩形1放在它们上面(横着放),它的高度 ,宽度
- 要形成正方形,需要:总宽度 (矩形1的高度),且总高度 ?混乱了
让我们重新理解标程:标程先检查 ,然后检查 。
当 时,条件 且 可以直接验证。这个条件对应的布局是:
- 矩形2和矩形3上下叠放(或左右并排放),矩形1放在旁边
- 由于输入保证了 和 ,所以这种条件恰好覆盖了一种特殊布局
算法步骤
对于每个测试用例:
- 调用
check()函数,判断当前方向下是否可行 - 如果不可行,交换所有矩形的长和宽(相当于允许旋转所有矩形,但题目说不允许旋转?注意标程这样做的原因:输入保证 从大到小、 从大到小,但实际放置时,我们可以选择将矩形的"长"作为高度或宽度。交换后相当于重新解释哪个是长哪个是宽,但保持排序性质)
- 再次调用
check(),如果可行输出"YES",否则"NO"
时间复杂度
每个测试用例 ,总时间复杂度 。
完整代码
#include <iostream> using namespace std; int main() { int t; cin >> t; int l1, b1, l2, b2, l3, b3; auto check = [&] () { // 情况1:三个矩形长度相等 if (l1 == l2 && l2 == l3) { // 子情况1:并排放 if (l1 == b1 + b2 + b3) return true; // 子情况2:两个并排放,一个放上面 if (b1 == b2 + b3 && 2 * l1 == b1) return true; return false; } // 情况2:后两个矩形长度相等 if (l2 == l3) { return (b2 + b3 == b1 && b1 == l2 + l1); } return false; }; while (t--) { cin >> l1 >> b1 >> l2 >> b2 >> l3 >> b3; if (check()) { cout << "YES\n"; } else { // 交换所有矩形的长和宽 swap(l1, b1); swap(l2, b2); swap(l3, b3); if (check()) { cout << "YES\n"; } else { cout << "NO\n"; } } } return 0; }
验证示例
以样例第2个测试用例:
第一次检查:
, ✓
输出"YES"以样例第4个测试用例:
第一次检查: 且 ?,所以
检查:,, ✗
交换后:
现在 不相等,且 也不满足
输出"NO"
- 1
信息
- ID
- 7137
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者