hdu - 3952 Fruit Ninja(简单几何)

来源:互联网 发布:数据挖掘工具有哪些 编辑:程序博客网 时间:2024/05/22 03:22

思路来自于:http://www.cnblogs.com/wuyiqi/archive/2011/11/06/2238530.html

枚举两个多边形的两个点组成的直线,判断能与几个多边形相交

因为最佳的直线肯定可以经过某两个点(可以平移到顶点处),所以暴力枚举两个点就好了

如果有模版的话,写代码就快多了。

代码如下:

#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <string>#include <cmath>#include <queue>#include <stack>#include <vector>#include <map>#define LL long long#define eps 1e-8#define N 15#define K 15using namespace std;struct Point{    double x, y;    Point operator - (const Point &t) const    {        Point temp;        temp.x = x-t.x;        temp.y = y-t.y;        return temp;    }    Point operator + (const Point &t) const    {        Point temp;        temp.x = x+t.x;        temp.y = y+t.y;        return temp;    }    bool operator == (const Point &t) const    {        return fabs(x-t.x)<eps&&fabs(y-t.y)<eps;    }};struct Figure{    int cnt;    Point poi[K];};struct Line{    double a, b, c;};Figure fig[N];Line t_Line(Point a, Point b)//点到直线的转化{    Line temp;    temp.a = a.y-b.y;    temp.b = b.x-a.x;    temp.c = a.x*b.y-b.x*a.y;    return temp;}bool Line_Inst(Line l1, Line l2, Point &p)//判断直线相交,并求交点{    double a1 = l1.a, b1 = l1.b, c1 = l1.c;    double a2 = l2.a, b2 = l2.b, c2 = l2.c;    if(fabs(a1*b2-a2*b1)<eps) return false;    p.x = (b1*c2-b2*c1)/(a1*b2-a2*b1);    p.y = (a1*c2-a2*c1)/(a2*b1-a1*b2);    return true;}double cross(Point a, Point b, Point c)//求向量的叉积,判断三点是否共线{    return (b.x-c.x)*(a.y-c.y)-(b.y-c.y)*(a.x-c.x);}bool dotOnSeg(Point a, Point b, Point c)//判断点是否在线段上{    if(a==c||b==c) return true;    return cross(a,b,c)<eps&&    (b.x-c.x)*(a.x-c.x)<eps&&    (b.y-c.y)*(a.y-c.y)<eps;}int main (){    int t, n, k, kk = 0;    scanf("%d", &t);    while(t--)    {        scanf("%d", &n);        for(int i = 1; i <= n; ++i)        {            scanf("%d", &k);            fig[i].cnt = k;            for(int j = 1; j <= k; ++j)                scanf("%lf %lf", &fig[i].poi[j].x, &fig[i].poi[j].y);        }        if(n<=2)        {            printf("Case %d: %d\n",++kk, n);            continue;        }        int ans = 0;        Point p;        for(int i = 1; i <= n; ++i)            for(int j = i+1; j <= n; ++j)                for(int k = 1; k <= fig[i].cnt; ++k)                    for(int l = 1; l <= fig[j].cnt; ++l)                    {                        Line l1 = t_Line(fig[i].poi[k], fig[j].poi[l]);//找到经过两个图形的顶点的直线                        int tt = 2;                        for(int ii = 1; ii <= n; ++ii)                        {                            if(ii==i||ii==j) continue;                            for(int jj = 1; jj < fig[ii].cnt; ++jj)                            {                                Line l2 = t_Line(fig[ii].poi[jj], fig[ii].poi[jj+1]);//图形的两个相邻节点组成一条直线                                if(Line_Inst(l1,l2,p)&&dotOnSeg(fig[ii].poi[jj], fig[ii].poi[jj+1], p))                                {//直线相交,并且交点位于线段上,即可证明直线l1穿过线段                                    ++tt;                                    break;                                }                            }                        }                        ans = max(ans, tt);                    }        printf("Case %d: %d\n",++kk, ans);    }    return 0;}


原创粉丝点击