1 条题解
-
1
#include<iostream> #include<vector> #include<algorithm> #include<cmath> #include<map> using namespace std; typedef double vec_type; double eps=1e-6; typedef pair<int,int> pii; inline int sign(int v){ if(v<0) return -1; if(v>0) return 1; return 0; } inline int sign(double v){ if(abs(v)<eps) return 0; if(v<0) return -1; if(v>0) return 1; return -2; } struct vec2{ vec_type x,y; vec2(){ x=0; y=0; } vec2(vec_type x,vec_type y){ this->x=x; this->y=y; } vec2& operator+=(const vec2& b){ x+=b.x; y+=b.y; return *this; } vec2 operator+(const vec2& b)const{ vec2 ret=*this; ret+=b; return ret; } vec2& operator-=(const vec2& b){ x-=b.x; y-=b.y; return *this; } vec2 operator-(const vec2& b)const{ vec2 ret=*this; ret-=b; return ret; } vec2& operator*=(vec_type v){ x*=v; y*=v; return *this; } vec2 operator*(vec_type v)const{ vec2 ret=*this; ret*=v; return ret; } vec2& operator/=(vec_type v){ x/=v; y/=v; return *this; } vec2 operator/(vec_type v)const{ vec2 ret=*this; ret/=v; return ret; } vec_type operator^(const vec2& b)const{ return x*b.y-y*b.x; } int operator<(const vec2& b)const{ if(sign(x-b.x)==0) return y<b.y; return x<b.x; } int operator==(const vec2& b)const{ if(sign(x-b.x)) return 0; if(sign(y-b.y)) return 0; return 1; } vec2 normalize()const{ double v=hypot(x,y); return vec2(x/v,y/v); } }; struct line{ vec2 p,v; line(vec2 p,vec2 v){ this->p=p; this->v=v; } line(){ } double get_k(){ return v.y/v.x; } double get_ik(){ return v.x/v.y; } }; struct segment{ vec2 p1,p2,v; line l; segment(vec2 p1,vec2 p2){ this->p1=p1; this->p2=p2; v=p2-p1; this->l.p=p1; this->l.v=v; } segment(){} }; double distance(const vec2& a, const vec2& b){ return hypot(a.x-b.x,a.y-b.y); } double distance(const vec2& p, const line& l){ return abs((p-l.p)^l.v.normalize()); } int point_is_point(const vec2& a,const vec2& b){ return sign(distance(a,b))==0; } int point_line_side(const vec2& point, const line& line){ return sign(line.v^(point-line.p)); } int parallel(const line& a,const line &b){ vec2 v1=a.v.normalize(); vec2 v2=b.v.normalize(); if(sign(v1^v2)==0) return 1; return 0; } int point_on_sigment(const vec2& point, const segment& segment){ if(point_is_point(point,segment.p1)||point_is_point(point,segment.p2)) return 1; if(sign((point-segment.p1)^segment.v)!=0) return 0; if( point.x>min(segment.p1.x,segment.p2.x)-eps&& point.x<max(segment.p1.x,segment.p2.x)+eps&& point.y>min(segment.p1.y,segment.p2.y)-eps&& point.y<max(segment.p1.y,segment.p2.y)+eps) return 1; return 0; } int segment_cross(const segment& s1,const segment& s2){ // 0 not cross // 1 cross // 2 vertex collision, s2.p1 on s1 // 3 vertex collision, s2.p2 on s1 if(abs(s1.v^s2.v)<eps) return 0; vec_type x1,x2,x3,x4; vec_type y1,y2,y3,y4; x1=min(s1.p1.x,s1.p2.x); x2=max(s1.p1.x,s1.p2.x); y1=min(s1.p1.y,s1.p2.y); y2=max(s1.p1.y,s1.p2.y); x3=min(s2.p1.x,s2.p2.x); x4=max(s2.p1.x,s2.p2.x); y3=min(s2.p1.y,s2.p2.y); y4=max(s2.p1.y,s2.p2.y); if(x3>x2||x1>x4) return 0; if(y3>y2||y1>y4) return 0; if(point_on_sigment(s2.p1,s1)) return 2; if(point_on_sigment(s2.p2,s1)) return 3; if( point_on_sigment(s1.p1,s2)|| point_on_sigment(s1.p2,s2)) return 4; if( point_line_side(s1.p1,s2.l)*point_line_side(s1.p2,s2.l)==-1&& point_line_side(s2.p1,s1.l)*point_line_side(s2.p2,s1.l)==-1) return 1; return 0; } vector<vec2> convex_hull(vector<vec2>&dta){ vector<int> vec; vector<vec2> ret; vector<int> used(dta.size()); sort(dta.begin(),dta.end(),[](vec2 a,vec2 b){ if(a.x==b.x) return a.y<b.y; return a.x<b.x; }); vec.push_back(0); for(int i=1,tp;i<dta.size();i++){ tp=vec.size()-1; while(vec.size()>=2&&(((dta[vec[tp]]-dta[vec[tp-1]])^(dta[i]-dta[vec[tp]]))<=0)){ used[vec.back()]=0; vec.pop_back(); tp--; } used[i]=1; vec.push_back(i); } int tmp=vec.size(); for(int i=dta.size()-1,tp;i>=0;i--) if(!used[i]){ tp=vec.size()-1; while(vec.size()>tmp&&(((dta[vec[tp]]-dta[vec[tp-1]])^(dta[i]-dta[vec[tp]]))<=0)){ vec.pop_back(); tp--; } vec.push_back(i); } vec.pop_back(); for(auto e:vec) ret.push_back(dta[e]); return ret; } vec2 line_intersection(const line& l1,const line& l2){ double k=((l2.p-l1.p)^l2.v)/(l1.v^l2.v); return l1.p+l1.v*k; } vector<vec2>dta[21]; vector<segment> segs; vector<segment> edges; vector<vec2> points; segment ray_to_segment(vec2 p1,vec2 p2){ vec2 v=(p2-p1).normalize(); p2=p1+v*1.5e5; return segment(p1,p2); } void get_tan(int i,int j){ vec2 p=dta[i][0]; vec2 v1,v2,v3; for(int k=0;k<dta[j].size();k++){ if(point_is_point(p,dta[j][k])) continue; if(k==0){ v1=dta[j][k]-dta[j].back(); }else{ v1=dta[j][k]-dta[j][k-1]; } if(k+1==dta[j].size()){ v2=dta[j][0]-dta[j][k]; }else{ v2=dta[j][k+1]-dta[j][k]; } v3=dta[j][k]-p; //TTT if((v1^v3)>-eps&&(v3^v2)>-eps){ // cout<<"A"<<i<<' '<<j<<endl; segs.push_back(ray_to_segment(p,dta[j][k])); }else if((v1^v3)<eps&&(v3^v2)<eps){ // cout<<"B"<<i<<' '<<j<<endl; segs.push_back(ray_to_segment(p,dta[j][k])); } } } void fst(vector<int> &a,bool inv){ for(int n=a.size(),step=1;step<n;step*=2){ for(int i=0;i<n;i+=2*step) for(int j=i;j<i+step;j++){ int &u=a[j],&v=a[j+step]; tie(u,v)=inv?pii(v,u-v):pii(u+v,u); } } } vector<int>vec; int n; double LIMIT=1e4; int dp[40009]; int solve(){ int nn=(1<<n)-1; for(int i=0;i<=nn;i++) dp[i]=100; dp[0]=0; int cnt=0; for(int i=nn;i>=0;i--){ if(vec[i]){ cnt++; for(int j=0;j<=nn;j++) if(dp[j]<100) dp[j|i]=min(dp[j|i],dp[j]+1); } } // cout<<n<<' '<<cnt<<endl; // for(int i=0;i<=nn;i++) // cout<<i<<' '<<dp[i]<<endl; return dp[nn]; } int main(void){ int t; int m; cin>>t; while(t--){ cin>>n; vec.clear(); vec.resize(1<<n); edges.clear(); segs.clear(); points.clear(); double x,y; if(n==1){ cout<<1<<endl; continue; } for(int i=0;i<n;i++){ dta[i].clear(); cin>>m; for(int j=0;j<m;j++){ cin>>x>>y; dta[i].emplace_back(x,y); } for(int j=0;j+1<m;j++) edges.push_back(segment(dta[i][j],dta[i][j+1])); edges.push_back(segment(dta[i][m-1],dta[i][0])); } for(int i=0;i<n;i++) for(int j=0;j<n;j++) get_tan(i,j); segs.push_back(segment(vec2(0,0),vec2(LIMIT,0))); segs.push_back(segment(vec2(0,0),vec2(0,LIMIT))); segs.push_back(segment(vec2(LIMIT,0),vec2(LIMIT,LIMIT))); segs.push_back(segment(vec2(0,LIMIT),vec2(LIMIT,LIMIT))); for(int i=0;i<segs.size();i++) for(int j=i+1;j<segs.size();j++) if(segment_cross(segs[i],segs[j])){ vec2 p=line_intersection(segs[i].l,segs[j].l); if(p.x<-eps || p.y<-eps || p.x>LIMIT+eps || p.y>LIMIT+eps) continue; points.push_back(p); } int vv=0; int cnt=0; map<vec2,int>mp; for(auto p:points){ cnt++; int v=0; for(int i=0;i<n;i++){ mp.clear(); segment s(dta[i][0],p); bool flag=true; for(auto e:edges){ int op=segment_cross(s,e); if(op==1){ flag=false; break; }else if(op==2 || op==3){ vec2 edge_p; if(op==2){ edge_p=e.p1; }else{ edge_p=e.p2; } if(mp.count(edge_p)){ if(mp[edge_p]==sign(s.v^e.v)){ if(edge_p==p && mp[edge_p]==-1) continue; if(edge_p==dta[i][0] && mp[edge_p]==1) continue; flag=false; break; } }else{ mp[edge_p]=sign(s.v^e.v); } } } if(flag) v|=(1<<i); vv|=v; } vec[v]=1; } cout<<solve()<<endl; } return 0; }
信息
- ID
- 881
- 时间
- 5000ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者