dp学习笔记3

今天学了求最长递增子序列的O(n*log(n))算法。。。

View Code
 1 /*
 2 【问题描述】
 3 PALMIA国家被一条河流分成南北两岸,南北两岸上各有N个村庄。北岸的每一个村庄有一个唯一的朋友在南岸,且他们的朋友村庄彼此不同。
 4 每一对朋友村庄想要一条船来连接他们,他们向政府提出申请以获得批准。由于河面上常常有雾,政府决定禁止船只航线相交(如果相交,则很可能导致碰船)。
 5 你的任务是编写一个程序,帮助政府官员决定批准哪些船只航线,使得不相交的航线数目最大。
 6 */
 7 /*
 8 测试样例:
 9 30 4
10 7
11 22 4
12 2 6
13 10 3
14 15 12
15 9 8
16 17 17
17 4 2
18 正确输出:
19 4
20 */
21 /*
22 于任意两条航线如果满足Ci<Cj 且Di<Dj 则两条航线不相交。
23 这样的话要想在一个序列里让所有的航线都不相交那比然满足,C1<C2<C3…Cans且D1<D2<D3…<Dans ,
24 也就是将C排序后求出最长的满足这个条件的序列的长度就是解
25 */
26 ///以下是n*log(n)的做法。。。
27 #include<iostream>
28 #include<algorithm>
29 const int N=5007;
30 using namespace std;
31 
32 struct Node{
33     int x,y;
34 }node[N];
35 int dp[N];
36 
37 int cmp(Node &a,Node &b){
38     if(a.x != b.x)
39         return a.x<b.x;
40     return a.y<b.y;
41 }
42 
43 int Search(int dp[],int len,int num){
44     int low=1,high=len;
45     while(low<=high){
46         int mid=(low+high)/2;
47         if(num==dp[mid])return mid;
48         else if(num<dp[mid])high=mid-1;
49         else low=mid+1;
50     }
51     return low;
52 }
53 
54 int main(){
55     int lx,ly;
56     while(~scanf("%d%d",&lx,&ly)){
57         int n;
58         scanf("%d",&n);
59         for(int i=1;i<=n;i++){
60             scanf("%d%d",&node[i].x,&node[i].y);
61         }
62         sort(node+1,node+n+1,cmp);
63         dp[0]=-1,dp[1]=node[1].y;
64         int len=1;
65         //n*log(n)算法求最长非下降子序列
66         for(int i=2;i<=n;i++){
67             int pos=Search(dp,len,node[i].y);
68             dp[pos]=node[i].y;
69             if(pos>len)len++;
70         }
71         printf("%d\n",len);
72     }
73     return 0;
74 }

 

posted @ 2013-03-26 17:09  ihge2k  阅读(538)  评论(0编辑  收藏  举报