DAG 模型
嵌套矩形问题
有 n 个矩形,每个矩形可以用两个整数 a, b 描述,表示它的长和宽。矩形 x(a,b) 可以嵌套在矩形 Y(c,d) 中,当且仅当 a<c, b<d,或者 b<c, a<d(相当于把矩形 X 旋转 90 度)。例如,(1,5) 可以嵌套在 (6,2) 内,但不能嵌套在 (3,4) 内。你的任务是选出尽量多的矩形排成一行,使得除了最后一个之外,每一个矩形都可以嵌套在下一个矩形内。如果有多解,矩形编号的字典序应尽量小。
解:
每个矩形可以用两个方向放置,但为了嵌套关系,我们需要标准化矩形:将长和宽统一成 (长,宽),其中 长 ≥ 宽。
这样处理后,判断矩形 i 能嵌套进矩形 j 的条件为:长_i < 长_j 且 宽_i < 宽_j。
因为 长_i ≥ 宽_i,所以如果两个维度都严格小于,那么旋转后也一定可以嵌套。
每个矩形看作一个结点。如果矩形 i 能嵌套进矩形 j,则建立一条有向边 i→j,边权为 1(表示嵌套一次,长度增加 1)。
注意:
- 这是有向的(嵌套关系单向)。
- 无环:如果 i 能嵌套进 j,则 i 的尺寸严格小于 j,不可能出现循环嵌套。因此这是一个 DAG。
目标:求这个 DAG 的 最长路径(边权为 1 时,路径长度 = 边数,结点数 = 边数 + 1,所以求最长路径的边数再加起始的一个矩形即可,或者直接让 dp[i] 表示从 i 开始的最多矩形数,包括 i 自己)。
#include <bits/stdc++.h>
using namespace std;
struct Rect {
int length; // 较大的边
int width; // 较小的边
// 构造函数:自动标准化
Rect(int a, int b) {
length = max(a, b);
width = min(a, b);
}
// 按长度排序,长度相同按宽度排序
bool operator<(const Rect& other) const {
if (length == other.length) return width < other.width;
return length < other.length;
}
};
int main() {
int n;
cout << ;
cin >> n;
vector<Rect> rects;
( i = ; i < n; i++) {
a, b;
cin >> a >> b;
rects.((a, b));
}
(rects.(), rects.());
;
ans = ;
( i = ; i < n; i++) {
( j = ; j < i; j++) {
(rects[j].length < rects[i].length && rects[j].width < rects[i].width) {
dp[i] = (dp[i], dp[j] + );
}
}
ans = (ans, dp[i]);
}
cout << << ans << endl;
cout << ;
( i = ; i < n; i++) cout << dp[i] << ;
cout << endl;
;
}



