矩阵嵌套问题
题意:有n个矩阵,每个矩阵可以用两个整数a、b描述,表示它的长和宽。矩阵X(a,b)可以嵌套在矩形Y(c,d)中,当且仅当a<c,b<d,或者b<c,a<d。输出最多嵌套的矩阵个数。
思路:如果矩阵X可以被Y嵌套,则相当于X到Y有一条路径,问题就转化成了在有向无环图中找最长路的问题。
这个问题是动态规划的基础问题。这里用动态规划解决:
设len(i)表示从结点i出发的最长路径长度。状态转移方程为:
len(i) = max{len(j)+1|(i,j)∈E}
E是边集。
实现:先把n个矩阵处理成一个邻接矩阵。
然后用记忆化搜索的方法实现动态规划方程。
输入:
10 1 2 2 4 5 8 6 10 7 9 3 1 5 8 12 10 9 7 2 2
输出:
5
#include<iostream> #include<memory.h> using namespace std; int gra[100][100]; int len[100];//从该点开始的最长路径长度 int n; struct mat { int a,b; }; int f(int pos) { if(len[pos] > 0) { return len[pos]; } len[pos] = 1; for(int i = 0; i < n; i ++) { if(gra[pos][i]) { len[pos] = max(len[pos], f(i) + 1); } } return len[pos]; } int main() { int ans = -1; cin >> n; mat nod[100]; memset(gra, 0, sizeof(gra)); memset(len, 0, sizeof(len)); for(int i = 0; i < n; i ++) { cin >> nod[i].a >> nod[i].b; } for(int i = 0; i < n; i ++) { for(int j = 0; j < n; j ++) { if((nod[i].a < nod[j].a && nod[i].b < nod[j].b) || (nod[i].a < nod[j].b && nod[i].b < nod[j].a)) { gra[i][j] = 1; } } } /* for(int i = 0; i < n; i ++) { for(int j = 0; j < n; j ++) { cout << gra[i][j] << ' '; } cout << endl; } */ for(int i = 0; i < n; i ++) { ans = max(ans, f(i)); } cout << ans << endl; return 0; }
打印矩阵编号字典序最小的:
#include<iostream> #include<memory.h> using namespace std; int gra[100][100]; int len[100];//从该点开始的最长路径长度 int n; struct mat { int a,b; }; int f(int pos) { if(len[pos] > 0) { return len[pos]; } len[pos] = 1; for(int i = 0; i < n; i ++) { if(gra[pos][i]) { len[pos] = max(len[pos], f(i) + 1); } } return len[pos]; } void print(int i) { cout << i << ' '; for(int j = 0; j < n; j ++) { if(gra[i][j] && len[i] == len[j] + 1) { print(j); break; } } } int main() { int ans = -1; cin >> n; mat nod[100]; memset(gra, 0, sizeof(gra)); memset(len, 0, sizeof(len)); for(int i = 0; i < n; i ++) { cin >> nod[i].a >> nod[i].b; } for(int i = 0; i < n; i ++) { for(int j = 0; j < n; j ++) { if((nod[i].a < nod[j].a && nod[i].b < nod[j].b) || (nod[i].a < nod[j].b && nod[i].b < nod[j].a)) { gra[i][j] = 1; } } } int matid = 0; for(int i = 0; i < n; i ++) { if(f(i) > ans) { ans = f(i); matid = i; } } cout << ans << endl; print(matid); return 0; }