POJ---3348 Cows

 Your friend to the south is interested in building fences and turning plowshares into swords. In order to help with his overseas adventure, they are forced to save money on buying fence posts by using trees as fence posts wherever possible. Given the locations of some trees, you are to help farmers try to create the largest pasture that is possible. Not all the trees will need to be used.

However, because you will oversee the construction of the pasture yourself, all the farmers want to know is how many cows they can put in the pasture. It is well known that a cow needs at least 50 square metres of pasture to survive.

Input

The first line of input contains a single integer, n (1 ≤ n ≤ 10000), containing the number of trees that grow on the available land. The next n lines contain the integer coordinates of each tree given as two integers x and y separated by one space (where -1000 ≤ x, y ≤ 1000). The integer coordinates correlate exactly to distance in metres (e.g., the distance between coordinate (10; 11) and (11; 11) is one metre).

Output

You are to output a single integer value, the number of cows that can survive on the largest field you can construct using the available trees.

Sample Input

4
0 0
0 101
75 0
75 101

Sample Output

151

翻译

你的南方朋友对建造篱笆和犁铧成剑很感兴趣。为了帮助他的海外冒险,他们被迫节省金钱购买篱笆桩使用树木作为篱笆桩尽可能。考虑到一些树木的位置,你要帮助农民努力创造最大的牧场。不是所有的树都需要被使用。然而,因为你将亲自监督牧场的建设,所有的农民都想知道他们能把多少牛放在牧场里。众所周知,奶牛需要至少50平方米的牧场才能生存。

输入

输入的第一行包含一个整数,n(1±n=10000),包含在可用土地上生长的树的数量。下一个n行包含每个树的整数坐标,给出为两个整数x和y y由一个空间分隔开(其中 -1000 ≤ x, y ≤ 1000)。整数坐标精确地与米的距离相关(例如,坐标(10;11)和(11;11)之间的距离是1米)。

输出

你要输出一个单一的整数值,牛的数量可以生存在最大的领域,您可以使用可用的树。

样例输入

4
0 0
0 101
75 0
75 101

样本输出

151

解题思路:

先用Andrew凸包算法求出围成最大面积所需的树的数量;然后按照分割法多边形求面积,求解即可;

其中用到的方法模板有:

1、求多边形面积:

把多边形分割成n-2个三角形,由于利用叉积求出的三角形的面积是有向的,所以以下算法针对凸多边形与非凸多边形皆有效。

 

代码实现:

double Polygon Area ( Pt* p, int n)
{
    double area =0;
    for ( int i =1;  i< n -1;  i ++)
        area += det ( p[ i]- p[0] , p[ i+1] - p [ 0]);
    return fabs ( area /2);
}

//其中det(a,b)函数是运算向量叉积的 (向量a × 向量b = ax * by − ay * bx)
//p[i] - p[0] 是运算向量(也可以自己写一个函数运算向量)

码实现 多边形的有向面积 这里返回正值

2、向量相关运算:

向量的加减运算:  (\vec{a}=({a_{x}} ,{a_{y}}),\vec{b}=({b_{x}} ,{b_{y}}))      (其中 \vec{a}= ({a_{x}},{a_{y}}), \vec{b}= ({b_{x}},{b_{y}}))\vec{a} \pm \vec{b}=({a_{x}}+{b_{x}} ,{a_{y}}+{b_{y}})

向量的模:\left | \vec{a} \right |= \sqrt{a_{x} * a_{x} + a_{y} *a_{y}}

向量的数乘:k*\vec{a}=(k*a_{x},k*a_{y})

向量的夹角:cos \alpha =\frac{\vec{a}\cdot \vec{b}}{\left | \vec{a} \right |*\left | \vec{ b } \right |}

向量的点乘运算:\vec{a}\cdot \vec{b}={a_{x}}*{b_{x}} +{a_{y}}*{b_{y}}

向量的叉乘运算:\vec{a}\times \vec{b}={a_{x}}*{b_{y}} -{a_{y}}*{b_{x}}

代码实现:

//向量的加法运算
Pt operator - ( Pt a, Pt b)
{
    return Pt( a. x- b. x, a. y- b. y );
}

//向量的减法运算
Pt operator + ( Pt a, Pt b)
{
    return Pt( a. x + b. x, a. y + b. y);
}

//向量的模
double Length ( Point q)
{
    return sqrt ( q. x* q. x+ q. y* q. y);
}

//向量的数乘
Pt operator * ( double A, Pt p)
{
    return Pt( p. x* A, p. y* A);
}

//向量的点乘
double dot ( Pt a, Pt b)
{
    return a. x * b. x + a. y * b. y;
}

//利用点乘和模求cos<a,b>
double Angle ( Vector A, Vector B)
{
    return acos ( dot ( A, B)/ Length ( A)/ Length ( B ));
}

//向量的叉乘
double det ( Pt a, Pt b)
{
    return a. x * b. y - a. y * b. x;
}

AC代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>//sort排序的头文件
#include <math.h>
typedef long long ll;
using namespace std;

//存储坐标
struct stu
{
    int x,y;
}p[10000+5],q[10000+5];

//自定义sort排序方式
bool cmp(stu a, stu b)
{
    if(a.x == b.x)  return a.y < b.y;
    return a.x < b.x;
}

//向量的叉乘
double det(stu a,stu b)
{
    return a.x * b.y - a.y * b.x;
}

//将坐标转化为向量
stu vec(stu a, stu b)
{
    stu c;
    c.x = a.x - b.x;
    c.y = a.y - b.y;
    return c;
}

//Andrew 求凸包算法
double Andrew(stu* p,int n, stu* ch)
{
    int m=0;
    sort(p, p+n, cmp);
    for(int i=0; i<n; i++)
    {
        while(m>1 && det(vec(ch[m-1],ch[m-2]),vec(p[i],ch[m-2])) <=0) m--;
        ch[m++] = p[i];
    }
    int k = m;
    for(int i=n-2;i>=0;i--)
    {
        while(m>k && det(vec(ch[m-1],ch[m-2]),vec(p[i],ch[m-2]))<=0)  m--;
        ch[m++] = p[i];
    }
    if(n>1) m--;
    return m;
}

//分解法求多边形面积
double sum(stu* p,int n)
{
    double area = 0;
    for(int i=1;i<n-1;i++)
    {
        area += det(vec(p[i],p[0]),vec(p[i+1],p[0]));
    }
    return fabs(area/2);
}

int main()
{
    int n;
    cin>>n;
    for(int i=0; i<n; i++)
    {
        cin>>p[i].x>>p[i].y;
    }
    int m = Andrew(p, n, q);
    double ans = sum(q,m);
    printf("%d\n",(int)(ans/50.0));
    return 0;
}

代码有点复杂,但是思路清晰,,,,这次是真的清晰  @)(^...^)(@       。。。。。。。。。          

猜你喜欢

转载自blog.csdn.net/A_B_C_D_E______/article/details/81235099
今日推荐