2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest-M:Rikka with Illuminations(计算几何)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/84790633

M. Rikka with Illuminations
time limit per test 8.0 s
memory limit per test 1024 MB
inputstandard input
outputstandard output

Rikka loves convex polygons, so she decides to install some illuminants to embellish polygons.

Now she has a large convex polygon with n sides. She also has m different points strictly outside the polygon which are all legal positions to install illuminants.

An illuminant can light up some exterior boundaries of the polygon.

Rikka wants to install some illuminants to light up all exterior boundaries of the polygon. She asks you to calculate the least number of illuminants which she needs and provide a feasible scheme.

Input
The input contains several test cases, and the first line contains a single integer T ( 1 T 100 ) T (1≤T≤100) , the number of test cases.

For each test case, the first line contains two integers n ( 3 n 1000 ) n (3≤n≤1000) and m ( 1 m 1000 ) m (1≤m≤1000) .

Each of the following n lines describes a vertex on the convex polygon with two integers x and y ( x , y 1 0 9 ) (|x|,|y|≤10^9) , the Cartesian coordinates of the vertex. All these vertices are given in counter-clockwise order and any three of them are not collinear.

Then the following m lines contain m different points outside the polygon describing all legal positions to install illuminants. Each of them contains two integers x and y ( x , y 1 0 9 ) (|x|,|y|≤10^9) , the Cartesian coordinates of a legal position. They are numbered from 1 to m. All these positions would not lie in some extension lines for the sides of the polygon.

Output
For each test case, if it’s impossible to light up all exterior boundaries of the polygon, output a single line with a single integer −1. Otherwise, output two lines. Firstly, output a line with a single integer k, representing the least number of illuminants Rikka needs to light up all the boundaries. Then, output a line with k space-separated distinct integers, describing a feasible scheme, each of which is the index of a selected position.

All feasible schemes are allowed, so you can output any of them.

Example
input
1
3 3
0 0
1 0
0 1
-1 -1
3 -1
-1 3
output
2
2 1

思路:对于每一个在凸多边形外的点,它所能照亮的线段是连续的。先求出每个点能照亮的线段区间,然后贪心即可。

对于每一个在凸多边形外的点,我们可以找出相对于这个点来说凸多边形上的最低点和最高点,那么这两个点之间的线段一定是能被照到的,但是这样并不能知道是哪一半的线段可以被照到。

然后我们可以随便从最低点(最高点)开始,判断向左延伸还是向右延伸,直到延伸到最高点(最低点),然后这个区间里的线段都是可以被照到的。

#include<bits/stdc++.h>
using namespace std;
const int MAX=2100;
typedef long long ll;
struct lenka{int l,r,index;};
struct Point{ll x,y;}A[MAX],B[MAX];
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;}
int cmp(const lenka& p,const lenka &q)
{
    if(p.l==q.l)return p.r>q.r;
    return p.l<q.l;
}
int check(Point A,Point B,Point C)//判断线段A和B是否在线段C的同侧
{
    if(cross(A,B)>=0&&cross(B,C)>=0)return 1;//A,B在C的同侧
    if(cross(A,B)<=0&&cross(B,C)<=0)return 1;//A,B在C的同侧
    return 0;
}
vector<lenka>QWQ;
vector<int>p,q;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)scanf("%lld%lld",&A[i].x,&A[i].y);
        for(int i=0;i<m;i++)scanf("%lld%lld",&B[i].x,&B[i].y);
        QWQ.clear();
        for(int i=0;i<m;i++)
        {
            int low=0;
            for(int j=0;j<n;j++)if(cross(A[j]-B[i],A[low]-B[i])>=0)low=j;      //找到相对于B[i]来说的最低点

            //判断是向low-1还是low+1延伸
            if(check(A[(low-1+n)%n]-A[low],A[(low+1)%n]-A[low],B[i]-A[low])==0)//向low-1延伸
            {
                for(int j=(low-2+n)%n;;j=(j-1+n)%n)
                {
                    if(check(A[j]-B[i],A[(j+1)%n]-B[i],A[(j+2)%n]-B[i])==0)
                    {
                        if((j+1)%n<=low)QWQ.push_back((lenka){(j+1)%n,low,i});//储存照亮的区间
                        else QWQ.push_back((lenka){(j+1)%n,low+n,i});
                        break;
                    }
                }
            }
            else                                                            //向low+1延伸
            {
                for(int j=(low+2)%n;;j=(j+1)%n)
                {
                    if(check(A[j]-B[i],A[(j-1+n)%n]-B[i],A[(j-2+n)%n]-B[i])==0)
                    {
                        if((j-1+n)%n<=low)QWQ.push_back((lenka){low,(j-1+n)%n+n,i});
                        else QWQ.push_back((lenka){low,(j-1+n)%n,i});
                        break;
                    }
                }
            }
        }
        sort(QWQ.begin(),QWQ.end(),cmp);
        p.clear();
        for(int i=0;i<QWQ.size();i++)
        {
            int ma=i;
            q.clear();
            q.push_back(QWQ[ma].index);
            while(QWQ[ma].r<QWQ[i].l+n)
            {
                int R=QWQ[ma].r;
                for(int j=i+1;j<QWQ.size()&&QWQ[j].l<=R;j++)if(QWQ[j].r>QWQ[ma].r)ma=j;
                if(QWQ[ma].r==R)break;
                q.push_back(QWQ[ma].index);
            }
            if(QWQ[ma].r>=QWQ[i].l+n&&(q.size()<p.size()||p.size()==0))p=q;
        }
        if(p.size()==0)puts("-1");
        else
        {
            printf("%d\n",p.size());
            for(int i=0;i<p.size();i++)printf("%d%c",p[i]+1,i==p.size()-1?'\n':' ');
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/84790633