题目大意:矩阵嵌套,不过维数是多维的。有两个个k维的盒子A(a1, a1...ak), B(b1, b2...bk),若能找到(a1...ak)的一个排列使得ai < bi,则盒子A可嵌套在盒子B中。给出n个k维的盒子,找出最长的可嵌套的盒子的序列。实际上是DAG上的动态规划问题。首先是判断A能否嵌套在B中,对盒子的k维数进行排序,依次比较即可。然后用d[i]表示以节点i为起点的最长路径的长度,可以得到状态转移方程:d(i) = max{d(j)+1}, (i,j)是图上的一条边。最后就是打印路径,根据转移方程递归打印路径即可。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 #define BOXN 35 6 #define DIMENSION 12 7 8 int k, n; // k is the number of boxes, n is the dimensionality 9 int box[BOXN][DIMENSION], d[BOXN]; // d[i] save the number of nodes in the longest path starting with node i 10 int G[BOXN][BOXN]; 11 12 bool is_nested(int *box1, int *box2) 13 { 14 // if box1 can be nested in box2, return true; otherwise false 15 for (int i = 0; i < n; i++) 16 if (box1[i] >= box2[i]) return false; 17 return true; 18 } 19 20 int dp(int i) // compute d[i] 21 { 22 if (d[i] > 0) return d[i]; 23 d[i] = 1; 24 for (int j = 1; j <= k; j++) 25 if (G[i][j]) 26 d[i] = max(d[i], dp(j)+1); 27 return d[i]; 28 } 29 30 void print_path(int i) // print the longest path starting with node i 31 { 32 printf("%d ", i); 33 for (int j = 1; j <= k; j++) 34 if (G[i][j] && d[i] == d[j]+1) 35 { 36 print_path(j); 37 break; 38 } 39 } 40 41 int main() 42 { 43 #ifdef LOCAL 44 freopen("in", "r", stdin); 45 #endif 46 while (scanf("%d%d", &k, &n) != EOF) 47 { 48 for (int i = 1; i <= k; i++) 49 for (int j = 0; j < n; j++) 50 scanf("%d", &box[i][j]); 51 for (int i = 1; i <= k; i++) 52 sort(box[i], box[i]+n); 53 memset(G, 0, sizeof(G)); 54 for (int i = 1; i <= k; i++) 55 for (int j = 1; j <= k; j++) 56 if (is_nested(box[i], box[j])) 57 G[i][j] = 1; 58 int ans = -1; 59 int start = 0; 60 memset(d, 0, sizeof(d)); 61 for (int i = 1; i <= k; i++) 62 { 63 int t = dp(i); 64 if (t > ans) 65 { 66 ans = t; 67 start = i; 68 } 69 } 70 printf("%d ", ans); 71 print_path(start); 72 printf(" "); 73 } 74 return 0; 75 } 76