FAQ | About Virtual Judge
题解:多维立方体的嵌套。嵌套条件:内层立方体对应边长必须完全小于外层立方体对应边长。寻找最大的嵌套层数,并输出嵌套序列。将问题抽象就会发现这其实还是一道DP的LIS,难点在于输出嵌套序列。为此我们需要在每个立方体层内边长排序的基础上再按照每个立方体最小边长层间再次排序,这样我们就能保证每次嵌套序列的增长只会出现在原序列的末尾,不会出现插入的情况,这样方便了我们保存每个节点的上一级,最终实现输出。
附代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
#include <limits>
#define MAX_N 12
#define MAX_K 32
using namespace std;
int m[MAX_K][MAX_N];
//node存储对应立方体信息,用于实现第二步排序
struct node{
int first;
int pos;
const bool operator < (node next) const
{
return this->first < next.first;
}
};
//point用于dp,保存长度和前一个节点
struct point{
int last;
int length;
};
int K,N;
int max_length;
point dp[MAX_K];
node n[MAX_K];
int save[MAX_K];
//判断是否符合嵌套条件
bool if_fit(int,int);
int main()
{
while( scanf("%d%d",&K,&N) != EOF )
{
for( int i = 0; i < K; i++ )
{
dp[i].last=i;dp[i].length=1;
for( int j = 0; j < N; j++ )
scanf("%d",&m[i][j]);
//第一步排序
sort(m[i],m[i]+N);
n[i].first=m[i][0];
n[i].pos=i;
}
//第二步排序
sort(n,n+K);
max_length=0;
for( int i = 0; i < K; i++ )
{
for( int j = 0; j < i; j++ )
{
if( if_fit( n[i].pos,n[j].pos ) )
{
//保证你找到的是当前嵌套序列的最后一个节点
if( dp[n[i].pos].length < dp[n[j].pos].length+1 )
{
dp[n[i].pos].length = dp[n[j].pos].length+1;
dp[n[i].pos].last = n[j].pos;
//最开始的时候吧max_length的更新放在这里,WA,有可能进不来
//max_length = max( max_length,dp[n[i].pos].length );
}
max_length = max( max_length,dp[n[i].pos].length );
}
}
}
int t=0;
for( int i = 0; i < K; i++ )
{
if( dp[i].length == max_length )
{
t=i;
break;
}
}
//倒着找回去,输出
for( int i = 0; i < max_length; i++ )
{
save[i]=t+1;
t=dp[t].last;
}
printf("%d\n",max_length);
for( int i = max_length-1; i >= 0; i-- )
{
printf("%d",save[i]);
if( i != 0 )
printf(" ");
}
printf("\n");
}
return 0;
}
bool if_fit( int x,int y )
{
for( int i = 0; i < N; i++ )
{
if( m[x][i] <= m[y][i] )
return false;
}
return true;
}