UVA 10635 王子和公主
| UVA?10635? |
| 【題目描述】:王子和公主 一個王子和公主在n*n的格子中行走,這些格子是有1....n^2的編號的。現在給定p+1個數,再給定q+1個數,公主和王子可以選擇其中某些格子行走,求他們最多能走幾個相同的格子。 |
| 【算法分析】: 這道題讀題是關鍵,然后我們發現需要的是公共的格子,又需要是這個步數最大化,可以想到最長公共子序列的模型。序列長度小于等于62500,最長公共子序列復雜度是n^2,超時,書上提供了把公共子序列退化到最長上升子序列的方法。以第一個系列為參照,編號1.....p+1,因為格子的數字是不重復的,且最大編號是62500,空間上滿足。給第二個序列重新標號,求最長上升子序列就可以了。代碼中的LIS方法是nlg2(n)的。 【總結】:首先要知道這個退化模型的局限性:1、數字不重復;2、標號小于等于62500(數字較小可存儲)。 解決第一個問題: 舉例:??????7?4?1?1?6?7?3 ????????????1?2?1?7?4?2?7 理想標號:??1?2?3?4?5?6?7 ????????????3?0?4?1?2?0?6 我們對每一個重復的數字,例如1,在1這個節點上用MAP<int,vector>,把3,4的序列用vector按順序存儲即可,讀數的時候,按照從小到大的順序標號即可。因為標號本身是從小到大的,所以保證解的最大化。那么到這里,我們統一用map存儲好了,出現一次的數字,在vector中只有一個元素。 解決第二個問題: 把大數統一用哈希表存儲就可以了,同樣能滿足編號不重復。 |
| 【完整代碼】: 1 #include<iostream> 2 3 #include<stdio.h> 4 5 #include<string.h> 6 7 #include<algorithm> 8 9 #include<stdlib.h> 10 11 #include<math.h> 12 13 #include<queue> 14 15 #include<vector> 16 17 #include<map> 18 19 #define MAXN 62500+10 20 21 #define MAXM 20000+5 22 23 #define oo 9556531 24 25 #define eps 0.000001 26 27 #define PI acos(-1.0)//這個精確度高一些 28 29 #define REP1(i,n) for(int i=0;i<(n);i++) 30 31 #define REP2(i,n) for(int i=1;i<=(n);i++) 32 33 using namespace std; 34 35 36 37 int A[MAXN]; 38 39 int B[MAXN]; 40 41 int C[MAXN];//存儲轉化位置信息 42 43 int n,p,q,cas=0; 44 45 int cnt; 46 47 void builtC() 48 49 { 50 51 cnt=0; 52 53 for(int i=0;i<MAXN;i++) C[i]=0; 54 55 for(int i=0;i<p+1;i++) C[A[i]]=i+1; 56 57 for(int i=0;i<q+1;i++) if (C[B[i]]!=0) A[cnt++]=C[B[i]]; 58 59 } 60 61 int d[MAXN],g[MAXN]; 62 63 int LIS(int a[], int n) 64 65 { 66 67 int i, j, * b = new int[n + 1], ans = 0; 68 69 b[ans] = - 0x3f3f3f3f; 70 71 for(i = 0; i < n; i ++) 72 73 { 74 75 j = upper_bound(b, b + ans + 1, a[i]) - b; 76 77 if(j > ans) 78 79 b[++ans] = a[i]; 80 81 else if(a[i] < b[j]) 82 83 b[j] = a[i]; 84 85 } 86 87 delete b; 88 89 return ans; 90 91 } 92 93 //} 94 95 int main() 96 97 { 98 99 cin>>cas; 100 101 for(int k=1;k<=cas;k++) 102 103 { 104 105 cin>>n>>p>>q; 106 107 for(int i=0;i<p+1;i++) cin>>A[i]; 108 109 for(int i=0;i<q+1;i++) cin>>B[i]; 110 111 builtC(); 112 113 cout<<"Case "<<k<<": "<<LIS(A,cnt)<<endl; 114 115 } 116 117 return 0; 118 119 }? ? |
| ?【關鍵詞】:最長上升子序列、最長公共子序列的轉化 |
轉載于:https://www.cnblogs.com/little-w/p/3525285.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的UVA 10635 王子和公主的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Otsu algorithm
- 下一篇: [itint5]棋盘漫步