矩形嵌套,矩形之间的“可嵌套”关系是一个典型的二元关系,二元关系可以用图来建模。如果矩形X可以嵌套在Y里,我们就从X到Y连一条有向边。
这个有向图是无环的,因为一个矩形无法直接或间接地嵌套在自己内部。就是求DAG上的最长路径。
用d[i]表示从节点i出发的最长长度。最终求的答案就是d[i]中的最大值。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int case_x, case_y, c, A[35][35], G[35][35], res[35], d[35];
int edg ( int i, int j ) {
int tmp = 1;
for ( int k = 1; k <= case_y; ++k ) {
if ( A[i][k] >= A[j][k] ) {
tmp = 0;
break;
}
}
return tmp;
}
int dp ( int i ) { //记忆化搜索
int &ans = d[i]; //此处较巧妙,任何对ans的读写实际上都是在对d[i]进行
if ( ans > 0 ) return ans;
ans = 1;
for ( int j = 1; j <= case_x; ++j )
if ( G[i][j] ) ans = max ( ans , dp( j ) + 1 );
return ans;
}
void print ( int a ) {
res[c++] = a;
for ( int i = 1; i <= case_x; ++i ) {
if ( G[a][i] && d[a] == d[i] + 1 ) { //可以确定d[a]是最长路,所以有向图的下一个点应为d[i] + 1 == d[a]
print ( i );
break;
}
}
}
int main ( ) {
while ( cin >> case_x >> case_y ) {
for ( int i = 1; i <= case_x; ++i ) {
for ( int j = 1; j <= case_y; ++j ) {
cin >> A[i][j];
}
sort ( A[i] + 1, A[i] + case_y + 1 );
}
memset ( G, 0, sizeof ( G ) );
for ( int i = 1; i <= case_x; ++i ) //此处是建图的过程
for ( int j = 1; j <= case_x; ++j ) {
if ( edg ( i, j ) ) G[i][j] = 1;
}
memset ( d, 0, sizeof ( d ) );
for ( int i = 1; i <= case_x; ++i )
dp ( i );
int MAX = -1, pos = -1;
for ( int i = 1; i <= case_x; ++i )
if ( d[i] > MAX ) {
MAX = d[i];
pos = i;
}
cout << MAX << endl;
c = 0;
print ( pos );
for ( int i = 0; i < c - 1; ++i )
cout << res[i] << " ";
cout << res[c - 1] << endl;
}
}