zoukankan      html  css  js  c++  java
  • HDU 4946 凸包

    给你n个点,具有速度,一个位置如果有其他点能够先到,则不能继续访问,求出里面这些点哪些点是能够无限移动的。

    首先我们考虑到,一个速度小的和一个速度大的,速度小的必定只有固定他周围的一定区域是它先到的,而其他地方都是速度大的先到。

    再来如果有相同速度的两点,前连线的中垂线则是它们先到的界限,如果一个点在多边形的内部,那么它必定会被与其他点连线的中垂线所包围。

    因此,只要选出最大速度的点,在里面找凸包即可。但是还有很多细节,比如点重合的情况...如果速度一样的点重合,该点也不能无限移动,但是求凸包时不能把这个点直接去掉,不然会有问题。

    /** @Date    : 2017-09-24 16:52:10
      * @FileName: HDU 4946 凸包.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1010;
    const double eps = 1e-8;
    
    
    struct point
    {
    	double x, y;
    	double v;
    	int idx;
    	point() {}
    	point(double _x, double _y)
    	{
    		x = _x, y = _y;
    	}
    	point operator -(const point &b) const
    	{
    		return point(x - b.x, y - b.y);
    	}
    	double operator *(const point &b) const
    	{
    		return x * b.x + y * b.y;
    	}
    	double operator ^(const point &b) const
    	{
    		return x * b.y - y * b.x;
    	}
    };
    
    double xmult(point p1, point p2, point p0)
    {
    	return (p1 - p0) ^ (p2 - p0);
    }
    
    double distc(point a, point b)
    {
    	return sqrt((double)((b - a) * (b - a)));
    }
    int sign(double x)
    {
    	if(fabs(x) < eps)
    		return 0;
    	if(x < 0)
    		return -1;
    	else
    		return 1;
    }
    
    ////////
    point stk[N];
    point p[N];
    int cmp(point a, point b)//以p[0]基准 极角序排序
    {
    	int t = xmult(a, b, p[0]);
    	if(t > 0)
    		return 1;
    	if(t == 0)
    		return distc(a, p[0]) < distc(b, p[0]);
    	if(t < 0)
    		return 0;
    }
    int cmpC(point a, point b)//水平序排序
    {
    	if(sign(a.x - b.x) == 0 && sign(a.y - b.y) == 0)
    		return a.v > b.v;
    	return sign(a.x - b.x) < 0 || (sign(a.x - b.x) == 0 && sign(a.y - b.y) < 0);
    }
    
    int cmpV(point a, point b)
    {
    	return a.v > b.v;
    }
    
    /*
    int GrahamA()
    {
        double mix, miy;
        mix = miy = 1e10;
        int pos = 0;
        for(int i = 0; i < n; i++)
        {
            if(p[i].y < miy || (p[i].y == miy && p[i].x < mix))
            {
                mix = p[i].x, miy = p[i].y;
                pos = i;
            }
        }
        swap(p[0], p[pos]);
        sort(p + 1, p + n, cmp);
        int top = 0;
        stk[0] = p[0];
        stk[1] = p[1];
        for(int i = 0; i < n; i++)
        {
            while(top >= 2 && sign(xmult(stk[top - 2], stk[top - 1], p[i])) < 0)
                top--;
            stk[top++] = p[i];
        }
        //stk[++top] = p[0];
        return top;
    }*/
    int ans[550];
    
    int Graham(point p[], int n)//水平序
    {
    	sort(p, p + n, cmpC);
    	int top = 0;
    	///
    	for(int i = 0; i < n; i++)
    		if(p[i].x == p[i + 1].x && p[i].y == p[i + 1].y && p[i].v == p[i + 1].v)//细节:注意比较速度,或者是特判下最后一个...
    			ans[p[i].idx] = -1;
    	///
    	for(int i = 0; i < n; i++)
    	{
    		if(ans[p[i].idx] == -1)////
    			continue;
    		while(top >= 2 && sign(xmult(stk[top - 2], stk[top - 1], p[i])) < 0)
    			top--;
    		stk[top++] = p[i];
    	}
    	//cout << top << endl;
    	int tmp = top;
    	for(int i = n - 2; i >= 0; i--)
    	{
    		if(ans[p[i].idx] == -1)////
    			continue;
    		while(top > tmp && sign(xmult(stk[top - 2], stk[top - 1], p[i])) < 0)
    			top--;
    		stk[top++] = p[i];
    	}
    	if(n > 1)
    		top--;
    	/////
    	for(int i = 0; i < top; i++)
    		ans[stk[i].idx] = 1;
    	//sort(p, p + n, cmpC);
    	for(int i = 0; i < n; i++)
    		if(p[i].x == p[i + 1].x && p[i].y == p[i + 1].y && p[i].v == p[i + 1].v)
    			ans[p[i].idx] = ans[p[i + 1].idx] = 0;
    	/////
    	return top;
    }
    
    
    int main()
    {
    	int icase = 0;
    	int n;
    	while(~scanf("%d", &n) && n)
    	{
    		MMF(ans);
    		MMF(stk);
    		for(int i = 0; i < n; i++)
    		{
    			double x, y, v;
    			scanf("%lf%lf%lf", &x, &y, &v);
    			p[i] = point(x, y);
    			p[i].v = v;
    			p[i].idx = i;
    		}
    		sort(p, p + n, cmpV);
    		printf("Case #%d: ", ++icase);
    		if(p[0].v == 0)
    		{
    			for(int i = 0; i < n; i ++)
    				printf("0");
    			printf("
    ");
    			continue;
    		}
    		int pos = 0;
    		for(int i = 0; i < n; i++)
    		{
    			pos = i;
    			if(p[i].v != p[i + 1].v)
    				break;
    		}
    		int tot = Graham(p, pos + 1);
    
    		for(int i = 0; i < n; i++)
    			printf("%d", ans[i]);
    		printf("
    ");
    	}
    	return 0;
    }
    /*
    
    5
    0 0 6
    3 3 6
    1 1 6
    0 3 6
    3 0 6
    
    9
    0 0 3
    0 1 3
    0 2 3
    1 0 3
    1 1 3
    1 2 3
    2 0 3
    2 1 3
    2 2 3
    
    3
    0 0 3
    1 1 2
    2 2 1
    
    3
    0 0 3
    0 0 3
    0 0 3
    
    8
    1 1 3
    2 1 3
    3 1 3
    3 2 3
    2 2 3
    1 2 3
    1 3 3
    3 3 3
    
    4
    0 0 3
    0 3 3
    3 0 3
    1 1 3
    
    6
    0 0 1
    -1 0 1
    1 0 1
    0 1 1
    0 -1 1
    0 -1 1
    
    */
    
  • 相关阅读:
    PHP 小tip .(@)符号和 php if 赋值
    PHP定义字符串时单引号和双引号的区别
    笔记本 windows 10 安装
    unix_12c_db_init
    教你如何使用php session
    js和 php 介绍
    PHP 简单答题系统
    PHP list() 函数
    PHP集成支付宝快速实现充值功能
    eclipse如何导入PHP的项目
  • 原文地址:https://www.cnblogs.com/Yumesenya/p/7589368.html
Copyright © 2011-2022 走看看