有n个矩形,每个矩形可以用两个整数a、b描述,表示它的长和宽。
矩形X(a,b)可以嵌套在矩形Y(c,d)中,当且仅当 a<c,b<d,或者b<c,a<d
选出尽可能多的矩形排成一行,使得除了最后一个之外,每一个矩形都可以嵌套在下一个矩形内。
输出这一排矩形,如果有多个矩形序列满足要求,按照字典序的顺序输出
、
这是一个很经典,也很有意思的问题,下面是ac代码
#include <cstdio>
#include <array>
#include <algorithm>
#include <bitset>
constexpr std::size_t NN { 1001U };
//题目给出矩形最大数目
static int N {};
std::array<int, NN> record{ {0,} };
//记忆化搜索dp的记录数组
std::array<int, NN> route;
//路径记录(按照矩形下标字典序排序)
int counter {};
std::bitset<NN * NN> nestable;
//行优先扁平化一个二维矩阵,记录每两个矩形i,j是否形成嵌套关系
typedef struct{ int w, h; } rectangle;
std::array<rectangle, NN> rectangles;
//矩形
inline
int const __index__(int i, int j)
{ return (i * N + j); }
//还原二维矩阵下标
inline
bool const __judge__(int i, int j){
return (std::min(rectangles[j].w, rectangles[i].h)
< std::min(rectangles[i].w, rectangles[i].h));
}
//min(a, b) < min(x, y)等价于
//(a < x && b < y) || (b < x && a < y)
int dfs(int index){
auto& d = record[index];
if(d) return d;
for(int Ot {}; Ot < N; ++Ot)
if(nestable[__index__(index, Ot)]
||(nestable[__index__(index, Ot)]
= __judge__(index, Ot)))//if的副作用
d = std::max(d, dfs(Ot));
return ++d;
}
//记忆化搜索(标准的模板。。)
void collect_by_order(int index){
route[counter++] = index;
for(int Ot {}; Ot < N; ++Ot)
if(nestable[__index__(index, Ot)]
&& record[index] == record[Ot] + 1){
collect_by_order(Ot);
break;
}
}
//按照字典序收集答案序列
int main(void){
std::scanf("%d", &N);
for(int i {}; i < N; ++i)
std::scanf("%d%d",
&rectangles[i].w,
&rectangles[i].h);
for(int i {}; i < N; ++i)
dfs(i);//每个都dfs试探
int start {};
for(int i {}; i < N; ++i)
if(record[start] < record[i])
start = i;
//以rectangle[start]为首个矩形得到最长dag路
collect_by_order(start);//字典序收集,方便输出
for(int i {}; i < counter; ++i)
std::printf("%d%c", route[i],
" \n"[(std::size_t)(i == counter - 1)]);//明文字符串
return 0;
}
该篇文章介绍了如何通过记忆化搜索和二维矩阵操作解决一个有趣的问题:给定一组矩形,选择尽可能多的矩形按顺序排列,使得除了最后一个,每个矩形都能嵌套在其后一个矩形内。作者提供了C++代码实现这一过程并按照字典序输出结果。
&spm=1001.2101.3001.5002&articleId=136122868&d=1&t=3&u=1f74acc5e2e44d53b958acd82ed8adc3)
995





