引例:NYOJ16
矩形嵌套
时间限制:3000 ms | 内存限制:65535 KB
难度:4
- 描述
- 有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。
- 输入
- 第一行是一个正正数N(0<N<10),表示测试数据组数,
每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽 - 输出
- 每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行
- 样例输入
-
1 10 1 2 2 4 5 8 6 10 7 9 3 1 5 8 12 10 9 7 2 2
- 样例输出
-
5
我们可以这样建模:将每个矩形视作一个结点,若矩形A能覆盖矩形B,那么就在作一条结点A指向结点B的有向路径,结果我们会得到一个DAG(有向无环图)。求符合条件的最多矩形数目,就是DAG中最长路径上的结点数目。
求DAG上的最长路径上的结点数目,我们可用记忆化搜索求解,(同poj1088滑雪)
代码如下:#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int MAXN=1005; vector<int> G[MAXN]; int V,E; int d[MAXN]; int dfs(int u) { if(d[u]>0) return d[u]; int ans=0; for(int i=0;i<G[u].size();i++) { ans=max(ans,dfs(G[u][i])+1); } return d[u]=ans; } int main() { memset(d,0,sizeof(d)); scanf("%d%d",&V,&E); for(int i=0;i<E;i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); } int ans=0; for(int i=1;i<=V;i++) ans=max(ans,dfs(i)); printf("%d ",ans+1); return 0; } /* 7 8 1 2 1 3 3 2 2 4 2 5 4 6 6 5 5 7 7 */
这样 矩形覆盖问题就迎刃而解。
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int MAXN=1005; vector<int> G[MAXN]; struct Rect{ int x,y; }rect[MAXN]; int n; void createG() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if((rect[i].x<rect[j].x&&rect[i].y<rect[j].y)||(rect[i].y<rect[j].x&&rect[i].x<rect[j].y)) { G[j].push_back(i); } } int d[MAXN]; int dfs(int u) { if(d[u]>0) return d[u]; int ans=0; for(int i=0;i<G[u].size();i++) ans=max(ans,dfs(G[u][i])+1); return d[u]=ans; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { G[i].clear(); scanf("%d%d",&rect[i].x,&rect[i].y); } createG(); memset(d,0,sizeof(d)); int ans=0; for(int i=1;i<=n;i++) ans=max(ans,dfs(i)); printf("%d ",ans+1); } return 0; }
该问题也可以转化为最长上升子序列问题求解。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=1000; struct Rect{ int x,y; }rect[1005]; int n; bool comp(const Rect &a,const Rect &b) { if(a.x==b.x) return a.y > b.y;//µ±±ß³¤ÏàͬʱÓдóµ½Ð¡ÅÅÐò else return a.x < b.x; } int dp[1005]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d%d",&rect[i].x,&rect[i].y); dp[i]=INF; } sort(rect,rect+n,comp); for(int i=0;i<n;i++) *lower_bound(dp,dp+n,rect[i].y)=rect[i].y; printf("%d ",lower_bound(dp,dp+n,INF)-dp); } return 0; }