POJ 1328

一开始的算法想错了,以为雷达的位置只能为整数。

后来在网上查,才明白过来。

要以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


其中源文件命名为main.c

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

                             http://poj.org/showmessage?message_id=162516

你可能感兴趣的:(poj,1328)