UVA1615 高速公路(highway)(重庆一中高2018级信息学竞赛测验5) 解题报告
2016-07-28 08:30
267 查看
【问题描述】 (注意:本题的距离D指的是每个村庄与最近的天桥的曼哈顿距离不超过D,而原题的距离D指的是每个村庄与最近的天桥的欧几里得距离不超过D)
BOB是一名优秀的工程设计师,他正在设计一条穿越的农村地区的高速公路。为了方便一些村庄的人安全而快捷穿越高速路,需要设计跨越高速公路的人行天桥。当然为了节约成本,BOB须尽量减少天桥的数量。
在BOB的设计图纸上,高速公路是一条长为L的线段,它的左端点是平面坐标系的原点,右端点是x轴正方向的某个点。所有村庄在坐标系中标记成点。
现在请你帮助BOB确定需要修建人行天桥的最少数量,满足每个村庄与最近的天桥的曼哈顿距离不超过D。
【输入格式】
第1行是一个整数L(1<=L<=10^9),表示高速公路的长度。
第2行是一个整数D(1<=D<=10^9),表示村庄离自己最近的天桥的不超过D。
第3行是一个整数n(n<=10^5),表示村庄数目。
接下来的n行,每行包含两个整数x,y,表示村庄的位置坐标(0<=x<=L,-D<y<D 且y!=0)。
【输出格式】
一个整数,表示修建人行天桥的最小数量。
【输入样例】
15
5
5
0 1
2 4
6 3
8 2
13 2
【输出样例】
3
【数据范围】
30%的数据满足:n<=10
70%的数据满足:n<=10,000
100%的数据满足:n<=100,000
【来源】
《算法竞赛》255页 uva 1615
做题思路(正解):根据题意,因为高速公路在x轴上,我们可以先计算出每个村庄可以到x轴(高速公路)上的位置的最小值和最大值,将它们看作一个区间,则该题就被转化为区间选点问题(即给你n个区间,选择尽量少的点,使得每个区间里至少有一个选择的点)。解决该类问题的核心思路为贪心,贪心策略为每次选择当前区间的最右端,这样才能既使得该区间里有一个点被选择,又使得可以该点在更多的区间里。所以,在实现贪心算法时,先按区间的右端点由小到大排序,每选择一个区间的右端点,就将包含该点的区间跳过,然后重复上述步骤。需要注意的是,村庄的纵坐标可能为负,在计算村庄到x轴的位置的最小值和最大值时,要取纵坐标的绝对值,我考试时就是错在了这里。
考后反思:看数据范围是一定要仔细,这次失分就是因为没有注意村庄的纵坐标可以为负。
BOB是一名优秀的工程设计师,他正在设计一条穿越的农村地区的高速公路。为了方便一些村庄的人安全而快捷穿越高速路,需要设计跨越高速公路的人行天桥。当然为了节约成本,BOB须尽量减少天桥的数量。
在BOB的设计图纸上,高速公路是一条长为L的线段,它的左端点是平面坐标系的原点,右端点是x轴正方向的某个点。所有村庄在坐标系中标记成点。
现在请你帮助BOB确定需要修建人行天桥的最少数量,满足每个村庄与最近的天桥的曼哈顿距离不超过D。
【输入格式】
第1行是一个整数L(1<=L<=10^9),表示高速公路的长度。
第2行是一个整数D(1<=D<=10^9),表示村庄离自己最近的天桥的不超过D。
第3行是一个整数n(n<=10^5),表示村庄数目。
接下来的n行,每行包含两个整数x,y,表示村庄的位置坐标(0<=x<=L,-D<y<D 且y!=0)。
【输出格式】
一个整数,表示修建人行天桥的最小数量。
【输入样例】
15
5
5
0 1
2 4
6 3
8 2
13 2
【输出样例】
3
【数据范围】
30%的数据满足:n<=10
70%的数据满足:n<=10,000
100%的数据满足:n<=100,000
【来源】
《算法竞赛》255页 uva 1615
做题思路(正解):根据题意,因为高速公路在x轴上,我们可以先计算出每个村庄可以到x轴(高速公路)上的位置的最小值和最大值,将它们看作一个区间,则该题就被转化为区间选点问题(即给你n个区间,选择尽量少的点,使得每个区间里至少有一个选择的点)。解决该类问题的核心思路为贪心,贪心策略为每次选择当前区间的最右端,这样才能既使得该区间里有一个点被选择,又使得可以该点在更多的区间里。所以,在实现贪心算法时,先按区间的右端点由小到大排序,每选择一个区间的右端点,就将包含该点的区间跳过,然后重复上述步骤。需要注意的是,村庄的纵坐标可能为负,在计算村庄到x轴的位置的最小值和最大值时,要取纵坐标的绝对值,我考试时就是错在了这里。
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int maxn=100005; int L,D,N; struct data { int x,y,a,b; }; data c[maxn]; bool cmp(data aa,data bb) { return aa.b<bb.b; } void solve() //区间选点问题 { sort(c+1,c+1+N,cmp); //按区间的右端点由小到大排序 int i=1,cnt=0; while(i<=N) { int now=c[i].b; cnt++; i++; while(i<=N && c[i].a<=now) i++; //将包含该点的区间跳过(因为这些区间里已经有一个选择的点了) } printf("%d\n",cnt); } int main() { //freopen("freeway.in","r",stdin); //freopen("freeway.out","w",stdout); scanf("%d%d%d",&L,&D,&N); for(int i=1;i<=N;i++) scanf("%d%d",&c[i].x,&c[i].y); for(int i=1;i<=N;i++) //计算每个村庄可以到x轴(高速公路)上的位置的最小值和最大值 { c[i].a=c[i].x-(D-abs(c[i].y)); c[i].b=c[i].x+(D-abs(c[i].y)); } solve(); return 0; }
考后反思:看数据范围是一定要仔细,这次失分就是因为没有注意村庄的纵坐标可以为负。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C++的template模板中class与typename关键字的区别分析
- C与C++之间相互调用实例方法讲解