dp,盒子嵌套问题。
用edge【i】【j】二维数组来记录盒子i 能够嵌套到盒子j 中。
在判断能否嵌套时,先将每个盒子的各个数据按从小到大排序,然后再逐项进行比较,如果每个数据都较小,则该盒子可被后者嵌套。
用dp【i】表示从盒子i开始的最长盒子串。
最后打印出最长盒子串时打出字典序最小的即可。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
int k,n;
bool first;
int edge[31][31], box[31][11], dp[31];
bool small(int a, int b) //判断盒子a是否比盒子b小
{
int i;
for( i=0; i<n; i++)
if( box[a][i] >=box[b][i])
return 0;
return 1;
}
int f( int i) //记忆化搜索
{
int& ans =dp[i];
if( ans> 0) return ans;
ans =1;
int j;
for( j=1; j<=k; j++)
if( edge[i][j] )
ans =max(ans, f(j)+1);
return ans;
}
void outpath( int i) //打印出路径,输出字典序最小的路径
{
if( !first)
printf(" ");
else
first =0;
printf("%d", i);
int j;
for( j=1; j<=k; j++)
if( edge[i][j] && dp[i] ==dp[j]+1)
{
outpath( j);
break;
}
}
int main()
{
while( scanf("%d%d", &k, &n)!=EOF )
{
int i,j;
for( i=1; i<=k; i++)
{
for( j=0; j<n; j++)
scanf("%d",&box[i][j] );
sort(box[i], box[i]+n);
}
memset( edge, 0,sizeof(edge));
memset( dp, 0,sizeof(dp) );
for( i=1; i<=k; i++) //找出所有盒子之间的边
for( j=1; j<=k; j++)
if( small( i,j))
edge[i][j] =1;
int c=0, flag=0;
for( i=1; i<=k; i++)
if( f(i)>c )
{
c =f(i);
flag =i;
}
printf("%d\n",c);
first=1;
outpath( flag);
printf("\n");
}
return 0;
}