题意:

    给出一个由n个点组成的凸包,以及凸包内的k个点,问是否能够在凸包上选择最多2k个点构造一个新的

  凸包,使得新的凸包覆盖原来的k个点。

    

    要求2k个点覆盖原本的k个点,只要对原k个点构造凸包,然后选择该凸包内一点O与该凸包的顶点连一条射线,其

  与大凸包相交的边的两端点即为要保留的点,小凸包的顶点个数<=k,所有结果最后一定存在。

 

  

    
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<set>
  7 #include<map>
  8 #include<stack>
  9 #include<time.h>
 10 #include<cstdlib>
 11 #include<cmath>
 12 #include<list>
 13 using namespace std;
 14 #define MAXN 100100
 15 #define eps 1e-7
 16 #define For(i,a,b) for(int i=a;i<=b;i++) 
 17 #define Fore(i,a,b) for(int i=a;i>=b;i--) 
 18 #define lson l,mid,rt<<1
 19 #define rson mid+1,r,rt<<1|1
 20 #define mkp make_pair
 21 #define pb push_back
 22 #define cr clear()
 23 #define sz size()
 24 #define met(a,b) memset(a,b,sizeof(a))
 25 #define iossy ios::sync_with_stdio(false)
 26 #define fre freopen
 27 #define pi acos(-1.0)
 28 #define inf 1e9+9
 29 #define Vector Point
 30 const int Mod=1e9+7;
 31 typedef unsigned long long ull;
 32 typedef long long ll;
 33 int dcmp(double x){
 34     if(fabs(x)<=eps) return 0;
 35     return x<0?-1:1;
 36 }
 37 double ox,oy;
 38 struct Point{
 39     double x,y,id;
 40     Point(){}
 41     Point(double x,double y):x(x),y(y) {}
 42     bool operator < (const Point &a)const { if(x==a.x) return y<a.y; return x<a.x; }
 43     Point operator - (const Point &a)const{ return Point(x-a.x,y-a.y); }
 44     Point operator + (const Point &a)const{ return Point(x+a.x,y+a.y); }
 45     Point operator * (const double &a)const{ return Point(x*a,y*a); }
 46     Point operator / (const double &a)const{ return Point(x/a,y/a); }
 47     void read(){ scanf("%lf%lf",&x,&y); }
 48     bool operator == (const Point &a)const{ return dcmp(x-a.x)==0 && dcmp(y-a.y)==0; }
 49 };
 50 double Dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; }
 51 ll dis(Vector a) { return sqrt(Dot(a,a)); }
 52 double Cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; }
 53 int ConvexHull(Point *p,int n,Point *ch){
 54     sort(p+1,p+1+n);
 55     int m=0;
 56     For(i,1,n){
 57         while(m>1 && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
 58         ch[m++]=p[i];
 59     }
 60     int k=m;
 61     Fore(i,n-1,1) {
 62         while(m>k && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
 63         ch[m++]=p[i];
 64     }
 65     if(n>1) m--;
 66     return m;
 67 }
 68 Point getInsect(Point p,Vector v,Point q,Vector w) {
 69     Vector u=p-q;
 70     double t=Cross(w,u)/Cross(v,w);
 71     return p+v*t;
 72 }
 73 Point p[200005],pp[200005],ch[200005],o;
 74 bool chk(Point p1,Point p2,Point q1,Point q2) {
 75     double c1=Cross(p2-p1,q1-p1),c2=Cross(p2-p1,q2-p1);    
 76     double c3=Dot(p2-p1,q1-p1),c4=Dot(p2-p1,q2-p1);
 77     if(dcmp(c1)*dcmp(c2)<0) {
 78         Point cp=getInsect(p1,p2-p1,q1,q2-q1);
 79         return Dot(cp-p1,p2-p1)>0;
 80     }
 81     return 0;
 82 }
 83 int n,k,res;
 84 set<int>ans;
 85 void solve(){
 86     ans.clear();
 87     scanf("%d",&n);
 88     For(i,0,n-1) p[i].read();
 89     scanf("%d",&k);
 90     For(i,1,k) pp[i].read();
 91     int m=ConvexHull(pp,k,ch);
 92     o=ch[0];
 93     For(i,1,m-1) o=(o+ch[i])/2;
 94     res=0;
 95     For(i,0,m-1) {
 96         while(!chk(o,ch[i],p[res],p[(res+1)%n])) res=(res+1)%n;
 97         ans.insert(res);ans.insert((res+1)%n);
 98     }
 99     set<int>::iterator it;
100     cout<<"Yes"<<endl;
101     cout<<ans.sz<<endl;
102     for(it=ans.begin();it!=ans.end();it++){
103         if(it!=ans.begin()) printf(" ");
104         printf("%d",(*it)+1);
105     }
106     cout<<endl;
107 }
108 int main(){
109 //    fre("in.txt","r",stdin);
110     int t=1;
111     cin>>t;
112     For(i,1,t) solve();
113     return 0;
114 }
View Code