UVA1615 高速公路(highway)(重庆一中高2018级信息学竞赛测验5) 解题报告

来源:互联网 发布:博罗园洲政府网络问政 编辑:程序博客网 时间:2024/05/02 01:32
【问题描述】  (注意:本题的距离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轴的位置的最小值和最大值时,要取纵坐标的绝对值,我考试时就是错在了这里。



#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;}

考后反思:看数据范围是一定要仔细,这次失分就是因为没有注意村庄的纵坐标可以为负。

0 0
原创粉丝点击