poj 3069
2016-08-29 20:19
246 查看
题目概述
数轴上有N个点,你需要以其中某些点为圆心做半径为R的圆,问最少做多少圆可使所有点都在圆中时限
1000ms/3000ms输入
第一行整数R,N,第二行N个整数,描述每个点的位置,输入到N=R=-1结束限制
0<=R<=1000;1<=N<=1000输出
每行一个数,为所求最少圆数样例输入
0 310 20 20
10 7
70 30 1 7 15 20 50
-1 -1
样例输出
24
讨论
贪心,由于给的点是无序的,先排序,然后拿一个圆,依次以每个点为圆心试,确保第一个没有被以前的圆覆盖到的点能被现在的圆覆盖到,否则就将现在的圆固定,固定到最后一次可以确保时圆心的位置,在固定的一刻,这个圆也是一个以前的圆了,这样既保证所有点都在圆中,又是最少从实现方面,则是维护左边界,然后枚举圆心,如果无法确保,则再看右边界最远可以到哪里,然后从下一个位置继续开始枚举圆心,枚举圆心时由于到达最后一个点后会退出循环导致结果不正确,故额外添加一个位置为正无穷的点作为最后一个点
其实道理是后来推出来的,一开始就靠直觉
题解状态
168K,16MS,C++,673B题解代码
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f #define MAXN 1004 #define memset0(a) memset(a,0,sizeof(a)) int R, N; int nums[MAXN]; int fun() { for (int p = 0; p < N; p++) scanf("%d", &nums[p]);//input nums[N++] = INF; sort(nums, nums + N); int left = 0, least = 0;//圆的左边界 需要的圆数 for (int p = 0; p < N; p++)//枚举圆心 if (nums[p] - R > nums[left]) {//当无法确保时 least++;//额外的圆 for (left = p; left < N&&nums[p - 1] + R >= nums[left]; left++);//枚举右边界 p = left;//移动圆心枚举的起始位置 } return least; } int main(void) { //freopen("vs_cin.txt", "r", stdin); //freopen("vs_cout.txt", "w", stdout); while (~scanf("%d%d", &R, &N) && (N != -1 || R != -1))//input printf("%d\n", fun());//output }
相关文章推荐
- poj 3069 Saruman's army
- POJ-3069-Saruman's Army(Java简单贪心)
- POJ 3069
- POJ 3069 Saruman‘s Army
- POJ 3617 Best Cow Line ||POJ 3069 Saruman's Army贪心
- POJ 3069 贪心
- POJ 3069 Saruman's Army
- poj 3069 Saruman's Army(贪心)
- POJ 3069 Saruman's Army (贪心)
- poj 3069 Saruman's Army
- POJ 3069 Saruman's Army
- POJ 3617 Best Cow Line ||POJ 3069 Saruman's Army贪心
- poj 3069 Saruman's Army
- poj 3069
- POJ-3069 Saruman's Army
- POJ-3069-Saruman's Army
- poj 3069 贪心 寻找满足某个要求的最大元素
- poj-3069-Saruman's Army
- POJ 3069 Saruman's Army
- POJ 3069 Saruman's Army