題解【CJOJ1070/UVA】嵌套矩形
阿新 • • 發佈:2019-02-28
矩形 name 路徑 names color 模板 c代碼 pan struct
P1070 - 【Uva】嵌套矩形
Description
有 n 個矩形,每個矩形可以用兩個整數 a, b 描述,表示它的長和寬。矩形 X(a, b) 可以嵌套在矩形 Y(c, d) 中當且僅當 a<c, b<d,或者 b<c, a<d(相當於把矩形 X 旋轉了 90°)。例如 (1, 5) 可以嵌套在 (6, 2) 內,但不能嵌套在 (3, 4) 內。
你的任務是選出盡量多的矩形,使得除了最後一個之外,每一個矩形都可以嵌套在下一個矩形內。
Input
第一行一個正整數 n (n <= 1000)。
接下來 n 行每行兩個正整數 a, b 表示矩形 i 的長和寬。
Output
第一行一個整數 k 表示符合條件的最多矩形數。
第二行 k 個整數依次表示符合條件矩形的編號,要求字典序最小。
Sample Input
8
14 9
15 19
18 12
9 10
19 17
15 9
2 13
13 10
Sample Output
4
4 8 3 2
Hint
最大嵌套深度為 4 。
4 個矩形分別是:4(9, 10) < 8(13, 10) < 3(18,12) < 2(15,19)
Source
入門經典,DP,DAG(有向無環圖)
此題是最長路模板。
最長路可以用DP來求,具體實現過程是這樣的:
inline int DP(int p) { if(dp[p]>0)//特判 { return dp[p]; } dp[p]=1;//初值 for(register int j=1; j<=n; j++)//枚舉所有出邊 { if(m[p][j]==1)//如果有邊 { dp[p]=max(dp[p],DP(j)+1);//就進行DP} } return dp[p];//返回 }
有了這個模板,此題就非常好做了:
先預處理處所有相連接的邊,然後進行DP,最後統計答案。
AC代碼:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 inline int read()//快速讀入 6 { 7 int f=1,x=0; 8 char c=getchar(); 9 10 while(c<‘0‘ || c>‘9‘) 11 { 12 if(c==‘-‘)f=-1; 13 c=getchar(); 14 } 15 16 while(c>=‘0‘ && c<=‘9‘) 17 { 18 x=x*10+c-‘0‘; 19 c=getchar(); 20 } 21 22 return f*x; 23 } 24 25 struct Node 26 { 27 int x,y; 28 } a[1005]; 29 int n,dp[1005],m[1005][1005],sum=-1; 30 31 inline int check(Node w,Node q)//預處理處矩形是否嵌套 32 { 33 if(w.x<q.x && w.y<q.y)return 1; 34 35 if(w.y<q.x && w.x<q.y)return 1; 36 37 return 0; 38 } 39 40 inline int DP(int p)//DP主過程 41 { 42 if(dp[p]>0) 43 { 44 return dp[p]; 45 } 46 47 dp[p]=1; 48 49 for(register int j=1; j<=n; j++) 50 { 51 if(m[p][j]==1) 52 { 53 dp[p]=max(dp[p],DP(j)+1); 54 } 55 } 56 57 return dp[p]; 58 } 59 60 inline void print(int ans) 61 { 62 printf("%d ",ans);//輸出當前邊 63 64 for(register int i=1; i<=n; i++)//枚舉所有出邊 65 { 66 if(m[ans][i]==1 && dp[ans]==dp[i]+1)//如果有邊 67 { 68 print(i);//遞歸輸出 69 70 break; 71 } 72 } 73 } 74 75 int main() 76 { 77 memset(dp,-1,sizeof(dp)); 78 memset(m,-1,sizeof(m)); 79 80 n=read(); 81 82 for(register int i=1; i<=n; i++) 83 { 84 a[i].x=read(),a[i].y=read(); 85 } 86 87 for(register int i=1; i<=n; i++) 88 { 89 for(register int j=1; j<=n; j++) 90 { 91 if(check(a[i],a[j])) 92 { 93 m[i][j]=1;//連邊 94 } 95 } 96 } 97 98 for(register int i=1; i<=n; i++)//計算各邊長度 99 { 100 if(dp[i]==-1) 101 { 102 dp[i]=DP(i); 103 } 104 } 105 106 for(register int i=1; i<=n; i++)//統計答案 107 { 108 if(dp[i]>dp[sum]) 109 { 110 sum=i; 111 } 112 } 113 114 printf("%d\n",dp[sum]);//輸出總數 115 116 print(sum);//打印路徑 117 118 return 0; 119 }
題解【CJOJ1070/UVA】嵌套矩形