UVALive

来源:互联网 发布:网络约车平台哪家好 编辑:程序博客网 时间:2024/06/03 23:46
/*************************************************************************    > Author: MentalOmega    > Mail: 965194745@qq.com    > Created Time:2017年10月13日    > function:题意说的是有n条直线把一个无限大的平面分割成了若干个区域,问每个区域有没有至少一个骑士在守卫。    这道题的直线有一个条件是No three rivers have a common point,那么就可以发现一个规律,平面数是1+直线数+交点数。    那么一开始就可以从求直线的交点的个数算出有多少个平面,然后枚举每条直线去分割平面 ************************************************************************/#include<bits/stdc++.h>#define Vector Pointusing namespace std;int n,m;const int MAXN = 50010;struct Point{    long long x,y;}point[50010];long long color[50010];long long mp[5001000];Point operator - (const Point &a,const Point &b){    return {a.x-b.x,a.y-b.y};}long long operator ^ (const Point &a,const Point &b){    return a.x*b.y-a.y*b.x;}struct Line{    Vector v;    int a , b , c ;}line[110];int main(){    if (fopen("in.txt", "r") != NULL)    {        freopen("in.txt", "r", stdin);        // freopen("out.txt", "w", stdout);    }    int t;    cin>>t;    while(t--)    {        memset(color,0,sizeof color);        memset(mp,0,sizeof mp);        scanf("%d%d",&n,&m);        for(int i=0;i<n;i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            Vector v={b,-a};            Point p={0,-c};            line[i].a = a ;            line[i].b = b ;            line[i].c = c ;            line[i].v = v;        }        for(int i=0;i<m;i++)        {            int x,y;            scanf("%d%d",&x,&y);            point[i]={x,y};        }        int cnt=1;        for(int i=0;i<n;i++)//计算平面数        {            int p=0;            for(int j=i+1;j<n;j++)            {                if(line[i].v^line[j].v)                    p++;            }            cnt+=p+1;        }        int top=0,botton=0;        for(int i=0;i<n;i++)        {            botton=(++top);//开始新的一轮的染色            for(int j=0;j<m;j++)            {                long long a , b , c ;                a = line[i].a ;                b = line[i].b ;                c = line[i].c ;                if( a * point[j].x + b * point[j].y + c > 0 )//这里只染直线上半部分的点                {                    if(mp[color[j]]<botton)//如果这个颜色的标号是上一轮的就更新标号                        color[j]=mp[color[j]]=top,top++;                    else                        color[j]=mp[color[j]];                }            }        }        set<long long> rec;//记录有多少种不同的颜色        for(int i=0;i<m;i++)        {            rec.insert(color[i]);        }        if(rec.size()==cnt) puts("PROTECTED");        else puts("VULNERABLE");    }    return 0;}

下面演示一次这个过程

这里每次染的是直线的下半部分
1
2
3
4

原创粉丝点击