矩形之间的"可嵌套"关系是一个典型的二元关系,二元关系可以用图来建模。如果矩形X可以嵌套在矩形Y里,我们就从X到Y连一条有向边。这个有向图是无环的,因为一个矩形无法直接或间接地嵌套在自己的内部。换句话说,它是一个DAG。这样,我们的任务便是求DAG上的最长路径。
可画图分析一下。
打印字典序最小的一个解
/*
*
嵌套矩形问题
描述#
有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
*/
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=1000+5;
int G[maxn][maxn];// 图用邻接矩阵保存
int w[maxn];
int h[maxn];
int d[maxn];
int T;
int N;
// 设d(i)表示从结点i出发的最长路长度
int dp(int i)
{
int &ans=d[i];
if(ans>0)
return ans;
ans=1;
for(int j=0;j<N;j++)
{
if(G[i][j])
{
ans=max(ans, dp(j)+1);
}
}
return ans;
}
void print_ans(int i)
{
cout<<i<<endl;
for(int j=0;j<N;j++)
if(G[i][j] && d[i]==d[j]+1)
{
print_ans(j);
break;
}
}
int main()
{
cin>>T;
while(T--)
{
// 输入矩形长宽
cin>>N;
memset(G, 0, sizeof(G));
memset(d, 0, sizeof(d));
for(int i=0;i<N;i++)
{
cin>>w[i]>>h[i];
if(w[i]>h[i]) swap(w[i], h[i]);
}
// 构建DAG
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
{
if(w[i]<w[j] && h[i]<h[j]) G[i][j]=1;
}
//dp
int ans=0;//嵌套长度
int best=0;//记录从哪个开始
// 没有确定路径的起点和终点,所以需要遍历所有起点(可以把任意矩形放在第一个和最后一个)
for(int i=0;i<N;i++)
{
int t=dp(i);
if(t>ans)
{
ans=t;
best=i;
}
}
cout<<ans<<endl;
print_ans(best);
}
return 0;
}
打印所有解
/*
*
嵌套矩形问题
描述#
有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
0 1 2 3 7
0 1 2 4 7
0 1 2 8 7
0 1 6 3 7
0 1 6 4 7
0 1 6 8 7
5 1 2 3 7
5 1 2 4 7
5 1 2 8 7
5 1 6 3 7
5 1 6 4 7
5 1 6 8 7
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=1000+5;
int G[maxn][maxn];
int w[maxn];
int h[maxn];
int d[maxn];
int T;
int N;
int dp(int i)
{
int &ans=d[i];
if(ans>0)
return ans;
ans=1;
for(int j=0;j<N;j++)
{
if(G[i][j])
{
ans=max(ans, dp(j)+1);
}
}
return ans;
}
int path[maxn];//记录递归过程中的路径
void print_ans_all(int i, int cur)
{
path[cur]=i;
if(d[i]==1)//说明到最后一个矩形
{
for(int j=0;j<=cur;j++)
{
cout<<path[j]<<" ";
}
cout<<endl;
return;
}
for(int j=0;j<N;j++)
if(G[i][j] && d[i]==d[j]+1)
{
print_ans_all(j, cur+1);
// break;
}
}
void print_ans(int i)
{
cout<<i<<" ";
for(int j=0;j<N;j++)
if(G[i][j] && d[i]==d[j]+1)
{
print_ans(j);
break;
}
}
int main()
{
cin>>T;
while(T--)
{
// 输入矩形长宽
cin>>N;
memset(G, 0, sizeof(G));
memset(d, 0, sizeof(d));
for(int i=0;i<N;i++)
{
cin>>w[i]>>h[i];
if(w[i]>h[i]) swap(w[i], h[i]);
}
// 构建DAG
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
{
if(w[i]<w[j] && h[i]<h[j]) G[i][j]=1;
}
//dp
int ans=0;//嵌套长度
int best=0;//记录从哪个开始
for(int i=0;i<N;i++)
{
int t=dp(i);
if(t>ans)
{
ans=t;
best=i;
}
}
cout<<ans<<endl;
for(int i = 0; i <= N; i++)
if(ans == dp(i)) print_ans_all(i, 0);
// print_ans(best);
}
return 0;
}