POJ 1654 Area [多边形面积]

题目链接:http://poj.org/problem?id=1654

You are going to compute the area of a special kind of polygon. One vertex of the polygon is the origin of the orthogonal coordinate system. From this vertex, you may go step by step to the following vertexes of the polygon until back to the initial vertex. For each step you may go North, West, South or East with step length of 1 unit, or go Northwest, Northeast, Southwest or Southeast with step length of square root of 2.

题目主要部分翻译:你将要去计算一种特殊多边形的面积。这个多边形的一个顶点是直角坐标系的原点。从原点,你能走到多边形的下一个顶点,直到回到初始的顶点。每走一步,你能走一个单位长度向北、西、南、东。或者你可以走根号2个单位长度向西北、东北、西南、东南。

最后需要求的是该多边形的面积。。比较简单。

唯一比较大的是最多顶点数为100 0000。。一百万。。时间上肯定没有什么问题。就是空间上有点压力。。如果全部用double的话。每个顶点花费16个字节,最多1000000个顶点那就是16000000个字节,算一下大约15625k,而题目要求最大空间为10000k。。这就不行了,如果全部用double的话,那就是ML了。。必须另求它路。。观察我们发现,所有的顶点都的格点。所以,我们存储点的时候可以用int来存,消耗的空间瞬间就降了一半。。。顺利就能AC了。。至于面积可能成为小数。那肯定是.5的结果。。自己小小处理一下就好了。。

#pragma comment(linker, "/STACK:102400000, 102400000")
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define INT long long
const int N = 1e6 + 10;
struct POINT
{
    int x, y;
    POINT() {}
    POINT(int a, int b){
        x = a;
        y = b;
    }
}p[N];
char order[N];
int top;

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

INT area()
{
    INT ans = 0;
    for(int i = 1; i < top; i ++){
        ans += (INT)cross(p[0], p[i], p[i + 1]);
    }
    if(ans < 0) return - ans;
    return ans;
}

int main()
{
//    freopen("1.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T --){
        scanf("%s", order);
        int len = strlen(order);
        top = 0;
        p[top ++] = POINT(0, 0);
        for(int i = 0 ; i < len ; i ++){
            if(order[i] == '5') break;
            if(order[i] == '8'){
                p[top ++] = POINT(p[top - 1].x, p[top - 1].y + 1);
            }
            if(order[i] == '2'){
                p[top ++] = POINT(p[top - 1].x, p[top - 1].y - 1);
            }
            if(order[i] == '6'){
                p[top ++] = POINT(p[top - 1].x + 1, p[top - 1].y);
            }
            if(order[i] == '4'){
                p[top ++] = POINT(p[top - 1].x - 1, p[top - 1].y);
            }
            if(order[i] == '9'){
                p[top ++] = POINT(p[top - 1].x + 1, p[top - 1].y + 1);
            }
            if(order[i] == '7'){
                p[top ++] = POINT(p[top - 1].x - 1, p[top - 1].y + 1);
            }
            if(order[i] == '3'){
                p[top ++] = POINT(p[top - 1].x + 1, p[top - 1].y - 1);
            }
            if(order[i] == '1'){
                p[top ++] = POINT(p[top - 1].x - 1, p[top - 1].y - 1);
            }
        }
        p[top] = POINT(0, 0);
        INT ans = area();
        if(ans % 2) printf("%lld.5\n", ans / 2);
        else printf("%lld\n", ans / 2);
    }
    return 0;
}

这里我们看到。。有些地方能用int的,尽量要用。这样不仅保证了数据存储的准确性,而且还节省了大量的空间。。

这又关系到了一种计算几何的素养。。。大家稍微体会一下。。。 - -。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值