现在的位置: 首页 > 综合 > 正文

zoj 2978 Phone Cell

2013年12月09日 ⁄ 综合 ⁄ 共 2536字 ⁄ 字号 评论关闭

同2167,只不过这次不是单位圆覆盖了,是给定半径了,方法都一样,比2167规模大不少。

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")
#define STOP system("pause")

using namespace std;

const int MAX = 4010;
struct point {double x,y;};
struct NODE { double t; int id, flag;};
point p[MAX];
NODE t[MAX];
double r;
const double eps = 1e-6;
bool dy(double x,double y)	{	return x > y + eps;}	// x > y 
bool xy(double x,double y)	{	return x < y - eps;}	// x < y 
bool dyd(double x,double y)	{ 	return x > y - eps;}	// x >= y 
bool xyd(double x,double y)	{	return x < y + eps;} 	// x <= y 
bool dd(double x,double y) 	{	return fabs( x - y ) < eps;}  // x == y
double disp2p(point a,point b) //  a b 两点之间的距离 
{
	return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
point l2l_inst_p(point u1,point u2,point v1,point v2)
{
	point ans = u1;
	double t = ((u1.x - v1.x)*(v1.y - v2.y) - (u1.y - v1.y)*(v1.x - v2.x))/
				((u1.x - u2.x)*(v1.y - v2.y) - (u1.y - u2.y)*(v1.x - v2.x));
	ans.x += (u2.x - u1.x)*t;
	ans.y += (u2.y - u1.y)*t;
	return ans;
}
void l2c_inst_p(point c,double r,point l1,point l2,point &p1,point &p2)
{
	point p = c;
	double t;
	p.x += l1.y - l2.y;
	p.y += l2.x - l1.x;
	p = l2l_inst_p(p,c,l1,l2);
	t = sqrt(r*r - disp2p(p,c)*disp2p(p,c))/disp2p(l1,l2);
	p1.x = p.x + (l2.x - l1.x)*t;
	p1.y = p.y + (l2.y - l1.y)*t;
	p2.x = p.x - (l2.x - l1.x)*t;
	p2.y = p.y - (l2.y - l1.y)*t;
}
void c2c_inst_p(point c1,double r1,point c2,double r2,point &p1,point &p2)
{
	point u,v;
	double t;
	t = (1 + (r1*r1 - r2*r2)/disp2p(c1,c2)/disp2p(c1,c2))/2;
	u.x = c1.x + (c2.x - c1.x)*t;
	u.y = c1.y + (c2.y - c1.y)*t;
	v.x = u.x + c1.y - c2.y;
	v.y = u.y - c1.x + c2.x;
	l2c_inst_p(c1,r1,u,v,p1,p2);
}
bool cmp(NODE a,NODE b)
{
	if( a.t == b.t ) return a.flag > b.flag;
	return xy(a.t, b.t);
}
double disp2p_sqr(point a,point b)
{
	return (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);
}
int solve(int n)
{
	int maxx = 1, cnt;
	bool ind[MAX]; 
	for(int i=0; i<n; i++)
	{
		cnt = 0;
		for(int k=0; k<n; k++)
		{
			if( i == k ) continue;
			if( disp2p_sqr(p[i], p[k]) > 4*r*r ) continue;
			point a,b;
			c2c_inst_p(p[i], r, p[k], r, a, b);//求得 两圆的交点,注意交点方向性,确定是标记1还是-1 
			t[cnt].id = k;
			t[cnt].flag = -1;
			t[cnt++].t = atan2(a.y - p[i].y, a.x - p[i].x);
			
			t[cnt].id = k;
			t[cnt].flag = 1;
			t[cnt++].t = atan2(b.y - p[i].y, b.x - p[i].x);
		}
		
		if( cnt == 0 ) continue;
		
		sort(t, t+cnt, cmp);
		memset(ind, false, sizeof(ind));
		
		int s = 0, sum = 1, j = 0;
		while( s < cnt/2 )
		{
			if( t[j].flag > 0 )
			{
				sum++;
				if( sum > maxx )
					maxx = sum;
				ind[t[j].id] = true;	// 标记已经进入了 
			}
			else
				if( ind[t[j].id] == true )	// 如果遇到出的点,而且进过,那么就走过了一个完整的弧,标记下 
				{
					s++;
					sum--;
				}	
			j++; j %= cnt;
		}
	}
	return maxx;		
}

int main()
{
	int n;

	while( ~scanf("%d", &n) && n )
	{
		scanf("%lf", &r);
		
		for(int i=0; i<n; i++)
			scanf("%lf%lf", &p[i].x, &p[i].y);
		
		int ans = solve(n);
		
		if( ans == 0 )
			ans = 1;
			
		printf("It is possible to cover %d points.\n", ans);

	}

return 0;
}

抱歉!评论已关闭.