NYOJ 16 矩形嵌套 【dp DAG】

题目链接:

  http://acm.nyist.net/JudgeOnline/problem.php?pid=16


dp:

  设d[i]表示从结点i出发的最长路径长度,状态转移方程为:

  d(i) = max{d(j)+1 | (i,j) ∈ E} 其中,E为边集

DAG:

  矩形之间的可嵌套关系是一种二元关系,二元关系用图来建模,若X可以嵌套在Y里,则建立一条X指向Y的有向边。

  这个有向图是无环的,因为一个矩形无法直接嵌套在自己内部,即此图是一个DAG。求最大的矩形嵌套数,就是求DAG上的最长路径。


 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 #define clr(c) memset(c, 0, sizeof(c));
 7 
 8 const int MAXL = 1000+10;
 9 typedef struct{
10     int length;
11     int width;
12 }rectangle;
13 
14 rectangle R[MAXL]; // 矩形数组
15 bool G[MAXL][MAXL]; // DAG的邻接矩阵
16 int d[MAXL]; // 状态转移数组
17 int Case, n, num1, num2;
18 
19 void CreatGraph(){ // 建图
20     clr(G);
21     for(int i = 0; i < n; i++){
22         for(int j = 0; j < n; j++){
23             if(R[i].length < R[j].length && R[i].width < R[j].width){
24                 G[i][j] = true; // i 嵌套在 j 中
25             }
26         }
27     }
28 }
29 
30 int dp(int i){
31     int& ans = d[i]; // 引用
32     if(ans > 0) return ans;
33     ans = 1;
34     for(int j = 0; j < n; j++){
35         if(G[i][j]) ans = max(ans, dp(j)+1); // dp(j)从j出发的最长路径
36     }
37     return ans;
38 }
39 
40 void print_ans(int i){
41     printf("%d ", i);
42     for(int j = 0; j < n; j++){
43         if(G[i][j] && d[i] == d[j]+1){
44             print_ans(j);
45             break; // 字典序最小,第一个符合条件的j输出后即退出
46         }
47     }
48 }
49 
50 int main(){
51     scanf("%d", &Case);
52     while(Case--){
53         scanf("%d", &n);
54         for(int i = 0; i < n; i++){ // 强行规定长 > 宽
55             scanf("%d%d", &num1, &num2);
56             R[i].length = max(num1, num2);
57             R[i].width = min(num1, num2);
58         }
59         CreatGraph();
60         clr(d); // 清空状态转移数组
61         int ans = 0, maxAns = 0;
62         for(int i = 0; i < n; i++){
63             int temp = dp(i);
64             //ans = max(ans, temp); // 输出最大的结果
65             if(temp > ans){ // 输出最大的结果,并记录最大值的编号(若有相同值取最小编号),用于输出路径
66                 ans = temp;
67                 maxAns = i;
68             }
69         }
70         printf("%d\n", ans);
71         //print_ans(maxAns); // 输出路径
72         //printf("\n");
73     }
74 
75     return 0;
76 }

 

posted @ 2015-10-06 21:03  快扶哀家去刷题  阅读(169)  评论(0编辑  收藏  举报