XMOJ 1133: 膜拜大牛 计算几何/两圆相交

1133: 膜拜大牛

Time Limit: 1 Sec  Memory Limit: 131072KiB
Submit: 9619  Solved: 3287

题目连接

http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1133

Description

由于wywcgs是个很菜的菜鸟,所以每到一个新的地方,他都必须去膜拜当地的大牛。但是大牛们都没空理他,所以无可奈何之下,wywcgs只能寻找其他 的办法。为了一次Orz到更多的大牛,他想到了一个好方法,就是在地图上找到每位大牛所在的位置,然后对着地图Orz,这样就可以膜拜到大牛了。我们可以 假设wywcgs的脑袋是半径为r的圆形。在Orz的时候,只要wywcgs的脑袋覆盖到了某位大牛所在的位置(边界也算覆盖),就算是Orz到了该位大 牛。每位大牛都有一个“NB度”,wywcgs当然想尽量能够Orz到更加NB的大牛,所以他想通过一次Orz,让自己Orz到的大牛的NB度的和最大。 由于他实在是太菜了,根本不知道该在哪里Orz才能达到这个效果。你能帮帮他吗?

Input

输入由多组数据组成。第一行是一个整数T(1<=T<=20),数据的组数。
  下面T组数据,每一组数据的第一行为一个正整数N(1<=N<=50),代表当地大牛的数量。接下来N行,每行有三个整数Xi Yi Wi(-20,000<=Xi,Yi<=20,000, 0<=Wi<=10^6),分别表示第i位大牛在地图上的横纵坐标和它的NB度,这个位置可以看成是一个面积为0的点。每组数据的最后一行是一个整数R(1<=R<=20,000),表示wywcgs脑袋的半径。

Output

总共输出T个整数。对每组数据,输出wy一次所能Orz到的大牛的最大NB度的和。

Sample Input

2
4
0 -10 1
0 10 1
-10 0 1
10 0 1
10
4
0 -10 1
0 10 1
-10 0 1
10 0 1
8

Sample Output

4
2

HINT


题解:

圆交点的最大值,转化为圆弧被多少个圆覆盖的问题

代码:

 

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200001
#define mod 10007
#define eps 1e-9
//const int inf=0x7fffffff;   //无限大
const int inf=0x3f3f3f3f;
/*
inline ll read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
*/
//**************************************************************************************


const double  eps = 1e-9;
const double pi = acos(-1.0);
const int N = 555;
    
struct point
{
    double x,y;
    int nb;
}p[N];
    
int n,r;
    
struct alpha
{
    double v;
    int nb;
    int flag;
    bool friend operator <(const alpha &a,const alpha &b)
    {   
        if(abs(a.v-b.v)<=eps)
            return a.flag>b.flag;
        else
            return a.v < b.v;
    }
}alp[N * 2];
    
double dis(point a, point b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
    
void solve(double R)
{
    int ans = 0;
    double theta,phi,dist;
    int i,j;
    for( i = 0;i < n;i++)
    {
        int k = 0;
        for( j = 0;j < n;j++)
        {
            if(i == j) continue;
            dist = dis(p[i],p[j]);
            if(dist - 2.0 * R > eps)//判断是否有交点
                continue;
            theta = atan2(p[j].y - p[i].y, p[j].x - p[i].x);//这条直线的斜率
            if(theta < eps)
                theta += 2 * pi;
            phi = acos(dist / (2.0 * R));
            alp[k].v = theta - phi + 2 * pi;
            alp[k].flag = 1;
            alp[k].nb=p[j].nb;
  
            alp[k + 1].v = theta + phi + 2 * pi;
            alp[k + 1].flag = 0;
            alp[k+1].nb=p[j].nb;
            k += 2;
        }
        sort(alp,alp + k);
        int sum = p[i].nb;
        ans=max(sum,p[i].nb);
        for( j = 0;j < k;j++)
        {
            if(alp[j].flag)
                sum +=alp[j].nb;
            else
                sum -=alp[j].nb;
            if(sum > ans)
                ans = sum;
        }
    }
    printf("%d\n",ans );
}
    
int main()
{
    int i,j,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            int x,y;
            int nb;
            scanf("%d %d %d",&x,&y,&nb);
            p[i].x=double(x);
            p[i].y=double(y);
            p[i].nb=nb;
        }
        scanf("%d",&r);
        solve(double(r));
    }
    return 0;
} 

 

posted @ 2015-04-01 22:18  qscqesze  阅读(1139)  评论(0编辑  收藏  举报