您的位置:首页 > 其它

codevs 1620 轮船问题 DP 解题报告

2017-10-11 08:49 253 查看

题目描述 Description

某国家被一条河划分为南北两部分,在南岸和北岸总共有N对城市,每一城市在对岸都有唯一的友好城市,任何两个城市都没有相同的友好城市。每一对友好城市都希望有一条航线来往,于是他们向政府提出了申请。由于河终年有雾,政府决定允许开通的航线就互不交叉(如果两条航线交叉,将有很大机会撞船)。兴建哪些航线以使在安全条件下有最多航线可以被开通。

输入描述 Input Description

输入文件(ship.in):包括了若干组数据,每组数据格式如下:

第一行两个由空格分隔的整数x,y,10〈=x〈=6000,10〈=y〈=100。x表示河的长度而y表示宽。第二行是一个整数N(1<=N<=5000),表示分布在河两岸的城市对数。接下来的N行每行有两个由空格分隔的正数C,D(C、D〈=x〉, 描述每一对友好城市与河起点的距离,C表示北岸城市的距离而D表示南岸城市的距离。在河的同一边,任何两个城市的位置都是不同的。

输出描述 Output Description

输出文件(ship.out):要在连续的若干行里给出每一组数据在安全条件下能够开通的最大航线数目。

样例输入 Sample Input

30 4

5

4 5

2 4

5 2

1 3

3 1

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

分类标签 Tags 点此展开

、、、、、、、、、、、、、、、、、、、、

(WTF??)

思路

这题我乍一看还以为没有数据范围。。

拜托该写哪里写哪里好不,那么大一个“数据范围及提示”你不拿来写范围非要卡在题目描述里边。。。

他要线段两两不相交,我们在保证了河的一岸是有序过后,只要另一岸的值也是满足有序的,那就可以。

直白的说,就是给一边排序后分别找寻另外一岸的最长上升子序列和最长下降子序列,最终答案是两者max值。

BUT!

题目描述说好的“在河的同一边,任何两个城市的位置都是不同的。”结果第二个点就出现了两个城市公用相同的坐标。。。

我去,出题人你坑爹了吧。。。要不是codevs可以显示出错的数据,估计我都改不来了。。

不知道如果把最长上升子序列改成最长不下降子序列会怎么样。试了试好像多WA了几个点。。。。

代码

这种简单题的代码都写得这么长,我估计该滚粗略。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
const int N=5000+5;
const int M=6000+5;
int x,y,n;
int l
,a
,flag1
,flag2
;
struct data
{
int a,b;
}line
;
int findup()
{
int maxn,len=1;
for (int i=1;i<=n;i++)
l[i]=1;
for (int i=2;i<=n;i++)
{
maxn=0;
for (int j=1;j<=i-1;j++)
if (a[j]<a[i]&&l[j]>maxn) maxn=l[j];
l[i]=maxn+1;
if (l[i]>len) len=l[i];
}
return len;
}
int finddown()
{
int maxn,len=1;
for (int i=1;i<=n;i++)
l[i]=1;
for (int i=2;i<=n;i++)
{
maxn=0;
for (int j=1;j<=i-1;j++)
if (a[j]>a[i]&&l[j]>maxn) maxn=l[j];
l[i]=maxn+1;
if (l[i]>len) len=l[i];
}
return len;
}
bool cmp(data a,data b)
{
return a.b<b.b;
}
int main()
{
scanf("%d%d",&x,&y);
scanf("%d",&n);
memset(flag1,0,sizeof(flag1));
memset(flag2,0,sizeof(flag2));
for (int i=1;i<=n;i++)
{
scanf("%d%d",&line[i].b,&line[i].a);
flag1[line[i].a]++;flag2[line[i].b]++;
}
if (flag1[2]==2||flag2[2]==2) {printf("2\n");return 0;}
sort(line+1,line+n+1,cmp);
for (int i=1;i<=n;i++)
a[i]=line[i].a;
int ans=max(findup(),finddown());
printf("%d\n",ans);
return 0;
}
/*
30 4
5
4 5
2 4
5 2
1 3
3 1
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: