NYOJ 16 矩形嵌套(经典动态规划)
Description
有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。
Input
第一行是一个正正数N(0<N<10),表示测试数据组数,
每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽
Output
每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行
Sample Input
1
10
1 2
2 4
5 8
6 10
7 9
3 1
5 8
12 10
9 7
2 2
Sample Output
5
思路
一、对于输入的a,b将较大的值赋给矩形的长,较小的值赋给矩形的宽,然后对矩形的长从小到大排序,这样保证了前面的矩阵不可能嵌套在后面中,然后只要对宽进行判断就行了。这样问题就转化为最长上升子序列了。
二、利用图模型解决,假设X可以嵌套在Y中,就从X到Y连一条边,这个有向图是无环的,也就是DAG图,这样,问题转化为求DAG上的最长路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn = 1005; struct Node{ int len,wid; }node[maxn]; bool cmp( struct Node xx, struct Node yy) { if (xx.len == yy.len) return xx.wid < yy.wid; else return xx.len < yy.len; } int main() { int T; scanf ( "%d" ,&T); while (T--) { int N,l,w,res = 0; int dp[maxn] = {0}; scanf ( "%d" ,&N); for ( int i = 0;i < N;i++) { scanf ( "%d%d" ,&l,&w); node[i].len = l > w?l:w; node[i].wid = w < l?w:l; } sort(node,node+N,cmp); for ( int i = 0;i < N;i++) //转化为求最长上升子序列 { dp[i] = 1; for ( int j = 0;j < i;j++) { if (node[i].wid > node[j].wid && node[i].len > node[j].len && dp[j] + 1 > dp[i]) { dp[i] = dp[j] + 1; } } res = max(res,dp[i]); } printf ( "%d\n" ,res); } return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int maxn = 1005; struct Node{ int len,wid; }node[maxn]; int dp[maxn],edge[maxn][maxn]; bool cmp( struct Node x, struct Node y) { if (x.len == y.len) return x.wid < y.wid; else return x.len < y.len; } void addedge( int N) { for ( int i = 0;i < N;i++) { for ( int j = i + 1;j < N;j++) { if (node[i].len < node[j].len && node[i].wid < node[j].wid) edge[i][j] = 1; } } } int solve( int i, int N) { int &ans = dp[i]; //为表项dp[i]声明了一个引用,这样,任何对ans的读写实际上都是在对dp[i]进行,实际上,当dp[i]换成dp[i][j][k]这样的长名字,该技巧优势更明显 if (ans > 0) return ans; ans = 1; for ( int j = 0;j < N;j++) if (edge[i][j]) ans = max(ans,solve(j,N) + 1); return ans; } int main() { int T,N,x,y; scanf ( "%d" ,&T); while (T--) { int tmp,res = 0; memset (dp,0, sizeof (dp)); memset (edge,0, sizeof (edge)); scanf ( "%d" ,&N); for ( int i = 0;i < N;i++) { scanf ( "%d%d" ,&x,&y); node[i].len = x>y?x:y; node[i].wid = x<y?x:y; } sort(node,node+N,cmp); addedge(N); for ( int i = 0;i < N;i++) { tmp = solve(i,N); res = tmp>res?tmp:res; } printf ( "%d\n" ,res); } return 0; } |
┆ 凉 ┆ 暖 ┆ 降 ┆ 等 ┆ 幸 ┆ 我 ┆ 我 ┆ 里 ┆ 将 ┆ ┆ 可 ┆ 有 ┆ 谦 ┆ 戮 ┆ 那 ┆ ┆ 大 ┆ ┆ 始 ┆ 然 ┆
┆ 薄 ┆ 一 ┆ 临 ┆ 你 ┆ 的 ┆ 还 ┆ 没 ┆ ┆ 来 ┆ ┆ 是 ┆ 来 ┆ 逊 ┆ 没 ┆ 些 ┆ ┆ 雁 ┆ ┆ 终 ┆ 而 ┆
┆ ┆ 暖 ┆ ┆ 如 ┆ 地 ┆ 站 ┆ 有 ┆ ┆ 也 ┆ ┆ 我 ┆ ┆ 的 ┆ 有 ┆ 精 ┆ ┆ 也 ┆ ┆ 没 ┆ 你 ┆
┆ ┆ 这 ┆ ┆ 试 ┆ 方 ┆ 在 ┆ 逃 ┆ ┆ 会 ┆ ┆ 在 ┆ ┆ 清 ┆ 来 ┆ 准 ┆ ┆ 没 ┆ ┆ 有 ┆ 没 ┆
┆ ┆ 生 ┆ ┆ 探 ┆ ┆ 最 ┆ 避 ┆ ┆ 在 ┆ ┆ 这 ┆ ┆ 晨 ┆ ┆ 的 ┆ ┆ 有 ┆ ┆ 来 ┆ 有 ┆
┆ ┆ 之 ┆ ┆ 般 ┆ ┆ 不 ┆ ┆ ┆ 这 ┆ ┆ 里 ┆ ┆ 没 ┆ ┆ 杀 ┆ ┆ 来 ┆ ┆ ┆ 来 ┆
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)