题目:给你一些n维的盒子,问最多能套多少个在一起。
分析:dp,lis,最大上升子序列,贪心。
因为,对于两个盒子来说,维度按照递增序嵌套时是最大嵌套可能(可归纳证明);
(1维显然成立;k维到k+1维最多2个维度不同,他们都按递增序有最大嵌套可能)
所以,每个盒子内部维度排序后,整体排序计算lis即可。
说明:见到一种解法,把图转化成偏序关系图,然后求最长路径,强大的图论(⊙_⊙)。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int box[33][33],f[33],p[33],n,m;
int cmp(const void* p, const void* q)
{
int *a = (int *)p,*b = (int *)q;
for (int i = 0 ; i < m ; ++ i)
if (a[i] != b[i])
return a[i] - b[i];
return a[m] - b[m];
}
void output(int s, int d)
{
if (s == p[s])
printf("%d\n%d",d,box[s][m]);
else {
output(p[s], d+1);
printf(" %d",box[s][m]);
}
}
int main()
{
while (~scanf("%d%d",&n,&m)) {
for (int i = 0 ; i < n ; ++ i) {
for (int j = 0 ; j < m ; ++ j)
scanf("%d",&box[i][j]);
box[i][m] = i+1;
sort(box[i], box[i]+m);
}
qsort(box, n, sizeof(box[0]), cmp);
for (int i = 0 ; i < n ; ++ i) {
f[i] = 1;
p[i] = i;
for (int j = 0 ; j < i ; ++ j) {
int flag = 1;
for (int k = 0 ; k < m ; ++ k)
if (box[j][k] >= box[i][k]) {
flag = 0;
break;
}
if (flag && f[i] < f[j]+1) {
f[i] = f[j]+1;
p[i] = j;
}
}
}
int max = 0;
for (int i = 1 ; i < n ; ++ i)
if (f[max] < f[i])
max = i;
output(max, 1);
printf("\n");
}
return 0;
}