1. 程式人生 > >poj2954 Triangle——pick定理

poj2954 Triangle——pick定理

題意:給定一個三角形,三角形的三個點都是整數點,問有多少個整數點嚴格在三角形內部

思路:典型的pick定理題目,公式為s=a+b/2-1,s為整數頂點的多邊形面積,a為它內部的整數點, b為它邊上的整數點(包括頂點),那麼題目要求的其實是b=(2*s+2-a)/2

s可以通過向量的叉積運算得到,a可以通過gcd得到,兩個點形成的線段包含的整數點為它們橫座標差值的絕對值和縱座標差值的絕對值的gcd-1,注意特判一下兩個差值都為0的情況

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
struct Point {
    ll x, y;
    Point(ll xx = 0, ll yy = 0) : x(xx), y(yy) {}
}p[3];
Point operator + (Point a, Point b) { return Point(a.x+b.x, a.y+b.y); }
Point operator - (Point a, Point b) { return Point{a.x-b.x, a.y-b.y}; }
ll Cross(Point a, Point b) { return a.x*b.y - a.y*b.x; }
ll mabs(ll x) {
    return x < 0 ? -x : x;
}
ll gcd(ll x, ll y) {
    return y == 0 ? x : gcd(y, x % y);
}
ll Area(Point a, Point b, Point c) {
    return mabs(Cross(a-c, b-c));
}
ll cnt(Point a, Point b) {
    ll x = mabs(a.x-b.x), y = mabs(a.y-b.y);
    if (x == 0 && y == 0) return 0;
    else return gcd(x, y)-1;
}
int main() {
    while (~scanf("%lld%lld%lld%lld%lld%lld", &p[0].x, &p[0].y, &p[1].x, &p[1].y, &p[2].x, &p[2].y)) {
        bool ok = true;
        for (int i = 0; i < 3; i++) {
            if (p[i].x != 0 || p[i].y != 0) { ok = false; break; }
        }
        if (ok) break;
        ll t = 3LL + cnt(p[0], p[1]) + cnt(p[1], p[2]) + cnt(p[0], p[2]);
        printf("%lld\n", ( Area(p[0], p[1], p[2]) + 2 - t) / 2);
    }
    return 0;
}