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

Hdu 1946 Area of Mushroom[凸包]

2017年05月27日 ⁄ 综合 ⁄ 共 2044字 ⁄ 字号 评论关闭

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4946

题目的意思是,给一些点,(代表学生),和这些点的速度,这些点要占领其他点(平面上所有的点,都是可以占领的),问这些点可以占领点是否是无限的。一个点被占领后,不能被其他的点占领。某一个点属于某个学生(也就是点),是走到该点所用时间小于其他所有点的时间。一开始,理解不了。以为,这些点都是动态的吧。其实,不然,其实判断某个点属于某个学生,只需要判断走到该点时间即可。。

思路:

官方题解的思路很好。

Code:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

const int N = 505;
const double eps = 1e-8;
struct POINT {
    double x, y;
    double v;
    int no;
}p[N], st[N], sp[N];
int n, m, top, ans[N];

double cross(POINT o, POINT a, POINT b){
    return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
}

double Distance(POINT a, POINT b){
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

bool cmp(POINT a, POINT b){
    if(a.y < b.y || (a.y == b.y && a.x < b.x)) return true;
    return false;
}
bool cmp1(POINT a, POINT b){
    double k = cross(p[0], a, b);
    if(k > eps) return true;
    else if(fabs(k) < eps && (Distance(p[0], a) - Distance(p[0], b)) < eps) return true;
    return false;
}

bool Judge(POINT a, POINT b, POINT c){
    double k = cross(a, b, c);
    if(k > eps) return true;
    else return false;
}

void Graham_scan(){
    if(n == 1) {
        if(ans[p[0].no] == -1)
        ans[p[0].no] = 1;
        return ;
    }
    sort(p, p + n, cmp);
    sort(p + 1, p + n, cmp1);
    top = 0;
    st[top ++] = p[0]; st[top ++] = p[1];
    for(int i = 2; i < n; i ++){
        while(top >= 2 && Judge(st[top - 1], st[top - 2], p[i])) top --;
        st[top ++] = p[i];
    }
    int ltop = top;
    for(int i = n - 2; i >= 0; i --){
        while(top != ltop && Judge(st[top - 1], st[top - 2], p[i])) top --;
        st[top ++] = p[i];
    }
    top --;

}//fisrt del the same point, stay one of the maxv.
int main(){
//    freopen("input.txt", "r", stdin);
    int k = 0, s;
    while(scanf("%d", &n) && n){
        s = n;
        memset(ans, -1, sizeof(ans));
        double maxv = -1;
        for(int i = 0; i < n; i ++){
            scanf("%lf %lf %lf", &p[i].x, &p[i].y, &p[i].v);
            p[i].no = i;
            maxv = max(maxv, p[i].v);
        }
        printf("Case #%d: ", ++ k);
        if(maxv == 0){
            for(int i = 0; i < n; i ++){
                printf("0");
            }
            printf("\n");
            continue;
        }
        m = 0;
        for(int i = 0; i < n; i ++){// v == maxv
            if(p[i].v != maxv) ans[p[i].no] = 0;
            else sp[m ++] = p[i];
        }
        sort(sp, sp + m, cmp);// del the same point.
        n = 0;
        p[n ++] = sp[0];
        for(int i = 1; i < m; i ++){
            if(!(sp[i].x == sp[i - 1].x && sp[i].y == sp[i - 1].y))
            p[n ++] = sp[i];
            else {
                ans[sp[i].no] = 0; ans[sp[i - 1].no] = 0;
            }
        }
        Graham_scan();
        for(int i = 0; i < top; i ++){
            if(ans[st[i].no] == -1) ans[st[i].no] = 1;
        }
        for(int i = 0; i < s; i ++){
            if(ans[i] == -1) ans[i] = 0;
        }
        for(int i = 0; i < s; i ++){
            printf("%d", ans[i]);
        }
        puts("");
    }
    return 0;
}

抱歉!评论已关闭.