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; }