只要上下边界不连通就可以。
然后两个图形相交就连边,拆点跑网络流就行了。
判相交比较麻烦(抑或是我写得麻烦)
#include <bits/stdc++.h>
using namespace std;
#define N 310
#define inf 1e9
#define eps 1e-8
#define M 1100000
int n,X,Y,c1,c2,cnt,S,T,tot,ans;
int pos[N][2],head[N<<1],nex[M],to[M],val[M],deep[N<<1];
queue<int>q;
void add(int x,int y,int v)
{
tot++;
nex[tot]=head[x];head[x]=tot;
to[tot]=y;val[tot]=v;
}
void ade(int x,int y,int v)
{add(x,y,v);add(y,x,0);}
void ad(int x,int y)
{
ade(pos[x][1],pos[y][0],inf);
ade(pos[y][1],pos[x][0],inf);
}
struct poi
{
double x,y;
poi(){}
poi(double x,double y):x(x),y(y){}
friend poi operator - (const poi &r1,const poi &r2)
{return poi(r1.x-r2.x,r1.y-r2.y);}
friend poi operator + (const poi &r1,const poi &r2)
{return poi(r1.x+r2.x,r1.y+r2.y);}
friend bool operator == (const poi &r1,const poi &r2)
{return fabs(r1.x-r2.x)<eps&&fabs(r1.y-r2.y)<eps;}
friend poi operator * (double x,const poi &r1)
{return poi(x*r1.x,x*r1.y);}
friend double operator * (const poi &r1,const poi &r2)
{return r1.x*r2.x+r1.y*r2.y;}
friend double operator ^ (const poi &r1,const poi &r2)
{return r1.x*r2.y-r2.x*r1.y;}
};
struct line
{
poi p,v;
line(){}
line(poi p,poi v):p(p),v(v){}
};
struct circle
{
poi p;double r;int num;
void read()
{
scanf("%lf%lf%lf",&p.x,&p.y,&r);
if(p.y<=r+eps)ade(S,pos[num][0],inf);
if(p.y+r+eps>=Y)ade(pos[num][1],T,inf);
}
}a[N];
struct polygon
{
poi p[6];int num;
void read()
{
scanf("%lf%lf%lf%lf",&p[2].x,&p[2].y,&p[4].x,&p[4].y);
p[1]=poi(p[2].x,p[4].y);
p[3]=poi(p[4].x,p[2].y);
if(p[2].y<=eps)ade(S,pos[num][0],inf);
if(p[1].y+eps>=Y)ade(pos[num][1],T,inf);
p[5]=p[1];
}
int ins(poi p1)
{return p1.x>p[1].x&&p1.x<p[4].x&&p1.y>p[2].y&&p1.y<p[1].y;}
}b[N];
poi intersect(line l1,line l2)
{
poi u=l1.p-l2.p;
double tmp=(u^l2.v)/(l2.v^l1.v);
return l1.p+tmp*l1.v;
}
double dis(poi p1,poi p2)
{return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}
int check(circle c1,poi p1,poi p2)
{
line l1=line(p1,p1-p2);
poi p=intersect(l1,line(c1.p,poi(-l1.v.y,l1.v.x)));
if(dis(c1.p,p)>c1.r+eps)return 0;
if(p==c1.p&&(p-p1)*(p-p2)>eps)return 0;
if((((c1.p-p1)^(c1.p-p))<0)^(((c1.p-p)^(c1.p-p2))<0))
return 0;
return 1;
}
int intersect(circle c1,circle c2)
{return dis(c1.p,c2.p)<c1.r+c2.r+eps;}
int intersect(polygon p1,polygon p2)
{
if(p1.p[1].x>p2.p[4].x||p2.p[1].x>p1.p[4].x)return 0;
if(p1.p[1].y<p2.p[2].y||p2.p[1].y<p1.p[2].y)return 0;
return 1;
}
int intersect(circle c1,polygon p1)
{
if(p1.ins(c1.p))return 1;
for(int i=1;i<=4;i++)
if(dis(c1.p,p1.p[i])<c1.r+eps)return 1;
for(int i=1;i<=4;i++)
if(check(c1,p1.p[i],p1.p[i+1]))
return 1;
return 0;
}
int dfs(int x,int mv)
{
if(x==T)return mv;
int tmp=0;
for(int i=head[x];i;i=nex[i])
if(val[i]&&deep[to[i]]==deep[x]+1)
{
int t=dfs(to[i],min(mv-tmp,val[i]));
if(!t)deep[to[i]]=-1;
tmp+=t;
val[i]-=t;val[i^1]+=t;
if(tmp==mv)break;
}
return tmp;
}
int bfs()
{
while(!q.empty())q.pop();
memset(deep,-1,sizeof(deep));
q.push(S);deep[S]=0;
while(!q.empty())
{
int t=q.front();q.pop();
for(int i=head[t];i;i=nex[i])
if(val[i]&&deep[to[i]]==-1)
{
deep[to[i]]=deep[t]+1;
q.push(to[i]);
if(to[i]==T)return 1;
}
}
return 0;
}
int main()
{
tot=1;
scanf("%d%d%d",&X,&Y,&n);
for(int i=1;i<=n;i++)
{
pos[i][0]=++cnt,pos[i][1]=++cnt;
ade(pos[i][0],pos[i][1],1);
}
S=++cnt;T=++cnt;
for(int i=1,tp;i<=n;i++)
{
scanf("%d",&tp);
if(tp==1)
{a[++c1].num=i;a[c1].read();}
else{b[++c2].num=i;b[c2].read();}
}
for(int i=1;i<=c1;i++)
for(int j=i+1;j<=c1;j++)
if(intersect(a[i],a[j]))
ad(a[i].num,a[j].num);
for(int i=1;i<=c2;i++)
for(int j=i+1;j<=c2;j++)
if(intersect(b[i],b[j]))
ad(b[i].num,b[j].num);
for(int i=1;i<=c1;i++)
for(int j=1;j<=c2;j++)
if(intersect(a[i],b[j]))
ad(a[i].num,b[j].num);
while(bfs())
ans+=dfs(S,inf);
printf("%d\n",ans);
return 0;
}