2014NOIP复赛模拟练习 设置喷水池 解题报告
2016-07-21 14:15
232 查看
【问题描述】
笑笑家的楼下是一条绿化带,可以用一条从0到10000的线段来表示。笑笑还知道这个绿化带上有n个地点(坐标为0到10000的整数)可以设置喷水池。已知喷水池的半径为r(正整数)。笑笑希望知道至少需要设置多少个喷水池才能把这个绿化带完全灌溉。
【输入格式】
第 1 行:两个整数n和r,分别表示可以设置喷水池的地点和喷水池的半径。
第 2 行:有n个数,分别表示可设置喷水池的地点坐标
【输出格式】
一个数,表示需要设置的喷水池的最少数量。
【输入样例】
5 4000
0 1000 3000 2000 9000
【输出样例】
2
【数据范围】
n<=1000,可以保证不存在无解情况。
解题思路:根据题意,每个喷水池都有一个坐标和相同的半径,因此可以将每个喷水池的喷水区域看作一条线段(一个区间),而绿化带是一条0-10000的线段([0,10000]),于是该题转化为区间覆盖问题,要求设置的喷水池的最少数量,即是求选择最少的线段(区间)去覆盖绿化带。求区间覆盖问题,可以使用贪心算法,将每条线段按左端点由小到大排序,假设要覆盖区间[s,t],首先在c[i].a(线段的左端点)<=s中,找一个c[i].b(线段的右端点)最大的,将s改为最大的c[i].b继续重复上述操作,最后所选的线段数即为答案。需要注意的是,在存每个喷水池的喷水区域时,喷水区域的范围是[0,10000]。
笑笑家的楼下是一条绿化带,可以用一条从0到10000的线段来表示。笑笑还知道这个绿化带上有n个地点(坐标为0到10000的整数)可以设置喷水池。已知喷水池的半径为r(正整数)。笑笑希望知道至少需要设置多少个喷水池才能把这个绿化带完全灌溉。
【输入格式】
第 1 行:两个整数n和r,分别表示可以设置喷水池的地点和喷水池的半径。
第 2 行:有n个数,分别表示可设置喷水池的地点坐标
【输出格式】
一个数,表示需要设置的喷水池的最少数量。
【输入样例】
5 4000
0 1000 3000 2000 9000
【输出样例】
2
【数据范围】
n<=1000,可以保证不存在无解情况。
解题思路:根据题意,每个喷水池都有一个坐标和相同的半径,因此可以将每个喷水池的喷水区域看作一条线段(一个区间),而绿化带是一条0-10000的线段([0,10000]),于是该题转化为区间覆盖问题,要求设置的喷水池的最少数量,即是求选择最少的线段(区间)去覆盖绿化带。求区间覆盖问题,可以使用贪心算法,将每条线段按左端点由小到大排序,假设要覆盖区间[s,t],首先在c[i].a(线段的左端点)<=s中,找一个c[i].b(线段的右端点)最大的,将s改为最大的c[i].b继续重复上述操作,最后所选的线段数即为答案。需要注意的是,在存每个喷水池的喷水区域时,喷水区域的范围是[0,10000]。
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<cmath> using namespace std; const int maxn=1005; int N,R; int A[maxn]; struct data { int a,b; }; data c[maxn]; bool cmp(data aa,data bb) { return aa.a<bb.a; } void solve() //解决区间覆盖问题 { int s=0,t=10000,cnt=0,i=1; while(i<=N && s<t) { int now=0; while(i<=N && c[i].a<=s) { if(c[i].b>now) now=c[i].b; //找到满足条件的最大的线段的右端点 i++; } cnt++; s=now; } printf("%d\n",cnt); } int main() { freopen("48.in","r",stdin); //freopen("48.out","w",stdout); scanf("%d%d",&N,&R); for(int i=1;i<=N;i++) scanf("%d",&A[i]); for(int i=1;i<=N;i++) { int aa=A[i]-R,bb=A[i]+R; aa=max(aa,0); //注意取值范围 bb=min(bb,10000); c[i].a=aa; c[i].b=bb; } sort(c+1,c+1+N,cmp); //按每条线段的左端点由小到大排序 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++之间相互调用实例方法讲解