一开始的算法想错了,以为雷达的位置只能为整数。
后来在网上查,才明白过来。
要以island为中心,一雷达辐射半径d为半径做圆,看是否能与coast(即x轴)相交。
如果该island与x轴有
两个交点: 就可以得到一个雷达位置的范围 [a,b]
一个交点: 范围为[a,a]
0个交点 : 直接输出 -1,表示不可能。
这样就可以得到一个范围数组。p[n]
其中p每个元素为一个结构体:
typedef struct cpoint{
double x1;
double x2;
}cpoint;
保证存储的时候x1 <= x2 (即,左边的交点放在x1中)
n表示交点个数。
再将p[n] 按照 x1 由小到大的顺序进行排序。
然就就可以由左到右对这些区域进行检测,当后面的区域的x1 大于 前一个区域的 x2的时候,表明两个区域分别需要一个雷达,这时雷达数目加一。
(贪心的体现:尽可能多的合并区域)
我的代码:
Source Code
Problem: 1328 | User: huntinux | |
Memory: 200K | Time: 32MS | |
Language: C | Result: Accepted |
- Source Code
#include <stdio.h> #include <math.h> #include <malloc.h> typedef struct point{ int x; int y; }point; typedef struct cpoint{ double x1; double x2; }cpoint; int calcrossp(point *p, cpoint *c,int pnum, int r) { int i; for(i = 0; i < pnum; i++){ if(p[i].y > r) return -1; c[i].x1 = p[i].x - sqrt((double)(r-p[i].y)*(r+p[i].y)); c[i].x2 = p[i].x + sqrt((double)(r-p[i].y)*(r+p[i].y)); } return 0; } void insort(cpoint *p, int pnum) { int i; cpoint valueInsert; int holepos; for(i = 1; i < pnum; i++){ valueInsert = p[i]; holepos = i; while(holepos > 0 && valueInsert.x1 < p[holepos-1].x1){ p[holepos]=p[holepos-1]; holepos--; } p[holepos] = valueInsert; } } int main(int argc, char *argv[]) { point *points; int pnum, r; int i; int casenum; cpoint *crossp; double right; int radarnum; casenum = 0; while(1){ // get points' num and r scanf("%d %d", &pnum, &r); if(pnum == 0 && r == 0) // break if pnum and r are all 0 break; // get the points and radar's distance points = (point *)calloc(pnum, sizeof(point)); crossp = (cpoint *)calloc(pnum, sizeof(cpoint)); for(i = 0; i < pnum; i++){ scanf("%d %d", &(points[i].x), &(points[i].y)); } // calculate the cross points if(r<=0 || calcrossp(points, crossp, pnum, r) == -1){ printf("Case %d: -1\n", ++casenum); free(points); // 不要忘记这里也要释放内存。 free(crossp); continue; } // sort the cross points insort(crossp, pnum); // cal the radar num radarnum = 1; right= crossp[0].x2; for(i = 1; i < pnum; i++){ if(crossp[i].x2 < right){ right= crossp[i].x2; //}else if(crossp[i].x2 >=right && crossp[i].x1 <= right){ }else if(crossp[i].x1 > right){ right= crossp[i].x2; radarnum++; } } printf("Case %d: %d\n", ++casenum, radarnum); free(points); free(crossp); } return 0; }
可用于编译并测试的shell脚本如下:
#! /bin/sh
#
# recompile and test the program
#
gcc -Wall main.c -lm && cat testdata | ./a.out
exit 0
testdata内容如下:
2 5
-3 4
-6 3
4 5
-5 3
-3 5
2 3
3 3
20 8
-20 7
-18 6
-5 8
-21 8
-15 7
-17 5
-1 5
-2 3
-9 6
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 7
9 6
10 5
0 0
2 3
0 2
2 3
2 3
0 2
1 3
3 3
1 2
-3 2
2 4
8 5
2 4
-4 4
-3 3
-3 1
-3 0
-1 0
0 5
6 0
3 0
1 2
-3 1
2 1
3 2
1 2
-3 1
2 1
1 2
0 2
2 3
0 2
2 3
4 -5
4 3
4 3
2 3
6 -9
3 -3
1 2
-3 2
2 1
6 2
1 2
1 2
1 2
-3 1
2 1
0 0
1 2
0 2
2 3
0 2
1 3
3 10
1 10
2 3
4 5
3 5
1 10
2 3
4 5
4 7
1 10
2 3
4 5
0 0
3 9
1 10
2 3
4 5
8 1
4 0
3 0
5 0
7 0
-5 0
-4 0
-3 0
1 0
0 0
正确输出:
Case 1: 1
Case 2: 2
Case 3: 4
Case 4: 1
Case 5: 1
Case 6: -1
Case 7: 3
Case 8: -1
Case 9: 2
Case 10: 1
Case 11: 1
Case 12: -1
Case 13: -1
Case 14: 2
Case 15: 1
Case 16: 1
Case 17: 1
Case 18: -1
Case 19: -1
Case 20: -1
Case 21: 4
特别要注意最后一组。这组出错了可能是排序没做好。
参考过的文章: 優YoU http://user.qzone.qq.com/289065406/blog/1299228061