poj 3348

来源:互联网 发布:论文数据造假有人查吗 编辑:程序博客网 时间:2024/04/29 16:31

题目概述

给定一个多边形中N个点的坐标x,y,每50面积可以放一个物体,求最多可放多少个物体

时限

2000ms/6000ms

输入

第一行正整数N,其后N行,每行两个整数x,y,输入到EOF为止

限制

1<=N<=10000;-1000<=x,y<=1000

输出

每行一个数,所求最多可放物体数

样例输入

4
0 0
0 101
75 0
75 101

样例输出

151

讨论

计算几何,求凸包面积,勉强算考了两个知识点,求凸包继续沿用之前的andrew算法,正好也省去点过少的两个特殊情况的处理,求面积,将多边形分割为多个小三角形,所有小三角形的一个顶点都是凸包的第一个点,其他的点都是凸包上相邻的点,其有向面积为共起点两向量的向量积的一半,最后加起来,除以50即可
实际上由于除以50的存在以及看上去好弱的数据,直接开int算面积和也不会出现偏差,不过还是避免这么做比较好

题解状态

208K,0MS,C++,1311B

题解代码

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define INF 0x3f3f3f3f  #define MAXN 10003#define memset0(a) memset(a,0,sizeof(a))#define EPS 1e-6struct Pt//point 点的结构{    int x, y;    bool operator<(Pt &b)const//直接重载小于 懒得单独写pred函数了    {        return y != b.y ? y < b.y : x < b.x;    }}pts[MAXN];int N;//点总数int stk[MAXN], top;//stack 数组模拟栈及其栈顶int xp(int x1, int y1, int x2, int y2, int x3, int y3){    return (x1 - x2)*(y3 - y2) - (y1 - y2)*(x3 - x2);}int fun(){    for (int p = 0; p < N; p++)        scanf("%d%d", &pts[p].x, &pts[p].y);//input    sort(pts, pts + N);//排序 下面是andrew算法    for (int p = 0; p < N; p++) {        while (top > 1 && xp(pts[p].x, pts[p].y, pts[stk[top - 2]].x, pts[stk[top - 2]].y, pts[stk[top - 1]].x, pts[stk[top - 1]].y) >= 0)            top--;        stk[top++] = p;    }    int stklen = top;    for (int p = N - 2; p >= 0; p--) {        while (top > stklen&&xp(pts[p].x, pts[p].y, pts[stk[top - 2]].x, pts[stk[top - 2]].y, pts[stk[top - 1]].x, pts[stk[top - 1]].y) >= 0)            top--;        stk[top++] = p;    }    double sum = 0;//初始化面积 用int也行    for (int p = 1; p < top - 2; p++) {        sum += xp(pts[stk[p]].x, pts[stk[p]].y, pts[0].x, pts[0].y, pts[stk[p + 1]].x, pts[stk[p + 1]].y) / 2.0;//算出有向面积 为了避免是负的而调整了出现的顺序    }    return sum / 50;}int main(void){    //freopen("vs_cin.txt", "r", stdin);    //freopen("vs_cout.txt", "w", stdout);    while (~scanf("%d", &N) && N) {//input        printf("%d\n", fun());//output        top = 0;    }}

EOF

0 0
原创粉丝点击