题解 P2782 【友好城市】

xzyxzy

2017-07-04 21:58:40

Solution

这是一本通上的一个例题,对于刚学动态规划的me来说当然不是一道水题,其实还是有一定难度的 首先我在本子上画了图,在数轴上描啊描,感觉这不和活动选择(一道贪心例题)一样么,于是就对它的一岸排了序,按照贪心策略来写(将每一对城市看作数轴上的一个区间,统计没有交集的区间最大个数)然后经老师提醒——这道题不能用贪心做!!如果两座城市一个从1到10,一个从2到11,贪心来讲是只能通过一对的,但是按题意可以都通过 所以,,在仔细琢磨了下,如果将一边排了序,能通过的城市对数一定是另一边的最长不下降子序列的长度(自己模拟下就好了,这样任意一对友好城市的连线与其他一对不会相交) 于是,难点又落在了求最长不下降子序列的长度上 用结构体a[i].num存储以a[i].s为最后一点的不下降子序列的长度,于是枚举每一个点(将枚举到的点设为A),看该点是否能与前面的点构成不下降子序列,于是又挨个枚举在该点之前的每一个点(将枚举到的点设为B),最终我们要的是满足1.B的s小于A的s,2.B的num(序列长度)是最大的,于是将a[B].num+1存入a[i].num中,使得a[i].num能与之前的最长序列合并组成新的最长序列 最后,线性地将a[i]枚举一遍,找到最大值(即是不下降子序列的最长长度)输出即可,此题得解 ```cpp #include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; struct hh{ int s; int n; int num=1; }a[5001]; int read() { char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); int h=0; while(ch<='9'&&ch>='0') { h=h*10+ch-48; ch=getchar(); } return h; } int n; int my(const hh&a,const hh&b) { return a.n<b.n; } int main() { n=read(); for(int i=1;i<=n;i++) { a[i].s=read(); a[i].n=read(); } sort(a+1,a+n+1,my);//以南岸的顺序排序 for(int i=2;i<=n;i++)//数北岸的最长不下降序列 { int max1=0; for(int w=1;w<i;w++) { if(a[i].s>a[w].s&&a[w].num>max1) { max1=a[w].num; } } a[i].num=max1+1; } int ans=0; for(int i=1;i<=n;i++) ans=ans>a[i].num?ans:a[i].num; cout<<ans; return 0; } ```