hdoj 3685 Rotational Painting

求出凸包和重心,然后一个个看凸包上的相邻点放在地面上能否放稳即可。

比赛中写的代码很搓。。。

/*
 * Author: stormdpzh
 * Created Time: 2012/8/17 15:10:30
 * File Name: f.cpp
 */
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <functional>

#define sz(v) ((int)(v).size())
#define rep(i, n) for(int i = 0; i < n; i++)
#define repf(i, a, b) for(int i = a; i <= b; i++)
#define repd(i, a, b) for(int i = a; i >= b; i--)
#define out(n) printf("%d\n", n)
#define mset(a, b) memset(a, b, sizeof(a))
#define wh(n) while(1 == scanf("%d", &n))
#define whz(n) while(1 == scanf("%d", &n) && n != 0)
#define lint long long

using namespace std;

const int INF = 1 << 30;
const int MaxN = 50005;
const double eps = 1e-12;

int sgn(double d)
{
    if(d > eps) return 1;
    if(d < -eps) return -1;
    return 0;
}

struct Point {
    double x, y;
    Point() : x(0.0), y(0.0) {}
    Point(double _x, double _y) : x(_x), y(_y) {}
    void read() {
        scanf("%lf%lf", &x, &y);
    }
};
Point pnt[MaxN], res[MaxN];
int n;
Point core;
struct Node {
    double x, dis;
    Node() {}
    Node(double _x, double _dis) : x(_x), dis(_dis) {}
    bool operator < (const Node &t) const {
        if(sgn(x - t.x) != 0) return sgn(x - t.x) < 0;
        else return sgn(dis - t.dis) < 0;
    }
};
set<Node> st;
set<Node>::iterator it;
int total;

bool mult(Point sp, Point ep, Point op)
{
    return sgn((sp.x - op.x) * (ep.y - op.y) - (ep.x - op.x) * (sp.y - op.y)) >= 0;
}

bool operator < (const Point &l, const Point &r)
{
    return sgn(l.y - r.y) < 0 || (sgn(l.y - r.y) == 0 && sgn(l.x - r.x) < 0);
}

Point operator - (const Point &l, const Point &r)
{
    return Point(l.x - r.x, l.y - r.y);
}

double operator * (const Point &l, const Point &r)
{
    return (l.x * r.x + l.y * r.y);
}

double operator ^ (const Point &l, const Point &r)
{
    return (l.x * r.y - l.y * r.x);
}

int get_convex()
{
    int i, len, k = 0, top = 1;
    sort(pnt, pnt + n);
    if (n == 0) return 0;
    res[0] = pnt[0];
    if (n == 1) return 1;
    res[1] = pnt[1];
    if (n == 2) return 2;
    res[2] = pnt[2];
    for (i = 2; i < n; i++) {
        while (top && mult(pnt[i], res[top], res[top - 1])) top--;
        res[++top] = pnt[i];
    }
    len = top;
    res[++top] = pnt[n - 2];
    for(int i = n - 3; i >= 0; i--) {
        while(top != len && mult(pnt[i], res[top], res[top - 1])) top--;
        res[++top] = pnt[i];
    }
    return top;
}

Point get_point()
{
    Point p, s;
    double tp, area = 0.0, tpx = 0.0, tpy = 0.0;
    p.x = pnt[0].x; p.y = pnt[0].y;
    for(int i = 1; i <= n; i++) {
        s.x = pnt[(i == n) ? 0 : i].x;
        s.y = pnt[(i == n) ? 0 : i].y;
        tp = fabs((p.x * s.y - s.x * p.y)); 
        area += tp / 2.0;
        tpx += (p.x + s.x) * tp; 
        tpy += (p.y + s.y) * tp;
        p.x = s.x; 
        p.y = s.y;
    }
    s.x = tpx / (6.0 * area); 
    s.y = tpy / (6.0 * area);
    return s;
}

bool judge(int x, int y)
{
    Point A = core - res[x];
    Point B = core - res[y];
    Point C = res[x] - res[y];
    if(sgn(A * (Point(0.0, 0.0) - C) <= 0)) return false;
    if(sgn(B * C) <= 0) return false;
    return true;
}

double get_dis(int x, int y)
{
    Point A = Point(0, 0) - res[x];
    Point C = res[y] - res[x];
    double area = fabs(A ^ C) / 2.0;
    return (area / sqrt((res[x].x - res[y].x) * (res[x].x - res[y].x) + (res[x].y - res[y].y) * (res[x].y - res[y].y)));
}

bool is_low(int x, int y)
{
    Point A = res[x], B = res[y];
    if(sgn(A.x - B.x) == 0) return sgn(A.x) < 0;
    if(sgn(A.y - B.y) == 0) return sgn(B.y) < 0;
    double tmp = (-A.x) * (A.y - B.y) / (A.x - B.x) + A.y;
    return sgn(tmp) < 0;
}

int gao()
{
    int cnt = 0;
    bool f = false;
    bool d = 0.0;
    st.clear();
    for(int i = 0; i < total; i++) {
        int j = (i + 1) % total;
        double x;
        double dis = get_dis(i, j);
        if(is_low(i,j)) dis = -dis;
        if(res[i].x - res[j].x == 0.0) {
            if(!f || d != dis) {
                if(judge(i, j)) {
                    cnt++;  
                    f = true;
                    d = dis;      
                }
            }
        }
        else {
            x = (res[i].y - res[j].y) / (res[i].x - res[j].x);
            if(st.find(Node(x, dis)) == st.end()) {
                if(judge(i, j)) {
                    cnt++;        
                    st.insert(Node(x, dis));
                }
            }
        }
    }
    return cnt;
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        for(int i = 0; i < n; i++) pnt[i].read();
        core = get_point();
        total = get_convex();
        out(gao());
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值