BZOJ3630
来源:互联网 发布:网络缓存级别 影音先锋 编辑:程序博客网 时间:2024/06/01 09:32
3630: [JLOI2014]镜面通道
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 478 Solved: 166
[Submit][Status][Discuss]
Description
在一个二维平面上,有一个镜面通道,由镜面AC,BD组成,AC,BD长度相等,且都平行于x轴,B位于(0,0)。通道中有n个外表面为镜面的光学元件,光学元件α为圆形,光学元件β为矩形(这些元件可以与其他元件和通道有交集,具体看下图)。光线可以在AB上任一点以任意角度射入通道,光线不会发生削弱。当出现元件与元件,元件和通道刚好接触的情况视为光线无法透过(比如两圆相切)。现在给出通道中所有元件的信息(α元件包括圆心坐标和半径xi,yi,ri,β元件包括左下角和右上角坐标x1,y1,x2,y2)
如上图,S到T便是一条合法线路。
当然,显然存在光线无法透过的情况,现在交给你一个艰巨的任务,请求出至少拿走多少个光学元件后,存在一条光线线路可以从CD射出。
下面举例说明:
现在假设,取走中间那个矩形,那么就可以构造出一条穿过通道的光路,如图中的S到T。
Input
第一行包含两个整数,x,y,表示C点坐标
第二行包含一个数字,n,表示有n个光学元件
接下来n行
第一个数字如果是1,表示元件α,后面会有三个整数xi,yi,ri分别表示圆心坐标和半径
第一个数字如果是2,表示元件β,后面会有四个整数x1,y1,x2,y2分别表示左下角和右上角坐标(矩形都平行,垂直于坐标轴)
Output
输出包含一行,至少需要拿走的光学元件个数m
Sample Input
1000 100
6
1 500 0 50
2 10 10 20 100
2 100 10 200 100
2 300 10 400 100
2 500 10 600 100
2 700 0 800 100
6
1 500 0 50
2 10 10 20 100
2 100 10 200 100
2 300 10 400 100
2 500 10 600 100
2 700 0 800 100
Sample Output
2
HINT
x<=100000,y<=1000,n<=300
Source
这个题啊,Excited!网络流最小割嘛,把每个图形拆点,即第i个图形向第i+n个图形连流量为1的无向边
如果一个图形与另一个图形相交,就连流量为INF的无向边
判相交的话,就是矩形与圆相交,搞一个计算几何求点到线段距离就好了
PS:与边界相交可以把边界视为矩形搞。
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>#define maxn 910#define maxm 300100#define pf(x) (1ll*(x)*(x))using namespace std;int n,bg,ed,head[maxn],dep[maxn],q[maxn],ql,qr,esz=2;long long x,y;struct edge{ int r,nxt,w;}e[maxm];struct Vector{ double x,y; Vector(){} Vector(double x,double y):x(x),y(y){} Vector operator-(const Vector& vec)const{ return Vector(x-vec.x,y-vec.y); }};double cross(const Vector& a,const Vector& b){ return a.x*b.y-a.y*b.x;}double dot(const Vector& a,const Vector& b){ return a.x*b.x+a.y*b.y;}double length(const Vector& a){ return sqrt((double)dot(a,a));}double distoseg(const Vector x,const Vector a,const Vector b){ Vector v1=b-a,v2=x-a,v3=x-b; if(dot(v1,v2)<0)return length(v2); if(dot(v1,v3)>0)return length(v3); return ((double)abs(cross(v1,v2)))/length(v1);}int dcmp(double a){ return fabs(a)<1e-7?0:(a>0?1:-1);}struct data{ long long x1,y1,x2,y2,att; void circle(long long x,long long y,long long r){ x1=x;y1=y;x2=r;att=1; } void square(long long x1,long long y1,long long x2,long long y2){ this->x1=x1;this->x2=x2; this->y1=y1;this->y2=y2; att=2; }}d[maxn];void addedge(int u,int v,int w){// printf("[%d,%d]\n",u,v); e[esz].r=v;e[esz].nxt=head[u]; e[esz].w=w;head[u]=esz++; e[esz].r=u;e[esz].nxt=head[v]; e[esz].w=0;head[v]=esz++;}bool isincir(long long x1,long long y1,data& d){ return pf(x1-d.x1)+pf(y1-d.y1)<=pf(d.x2);}bool isinsq(long long x1,long long y1,data& d){ return d.x1<=x1&&x1<=d.x2&&d.y1<=y1&&y1<=d.y2;}bool cirandcir(data& x,data& y){ return pf(x.x1-y.x1)+pf(x.y1-y.y1)<=pf(x.x2+y.x2);}bool pd(long long x1,long long y1,long long x2,long long y2,long long x,long long y,long long r){ return dcmp(distoseg(Vector(x,y),Vector(x1,y1),Vector(x2,y2))-r)<=0;}bool bfs(){ ql=qr=0; q[qr++]=bg; memset(dep,0,sizeof(dep)); dep[bg]=1; while(ql<qr){ int x=q[ql++]; for(int t=head[x];t;t=e[t].nxt)if(!dep[e[t].r]&&e[t].w) dep[e[t].r]=dep[x]+1,q[qr++]=e[t].r; } return dep[ed]!=0;}int find(int u,int flow){ if(u==ed)return flow; int a=0,used=0; for(int t=head[u];t;t=e[t].nxt)if(e[t].w&&dep[e[t].r]==dep[u]+1&&(a=find(e[t].r,min(flow,e[t].w)))){ e[t].w-=a;e[t^1].w+=a; used+=a; if(used==flow)return used; } if(!used)dep[u]=0; return used;}bool check(int i,int j){ if(d[i].att==1&&d[j].att==1){ if(cirandcir(d[i],d[j])||cirandcir(d[i],d[j])) return true; } else if(d[i].att==2&&d[j].att==2){ if(isinsq(d[i].x1,d[i].y1,d[j])||isinsq(d[i].x2,d[i].y1,d[j]) ||isinsq(d[i].x1,d[i].y2,d[j])||isinsq(d[i].x2,d[i].y2,d[j])|| isinsq(d[j].x1,d[j].y1,d[i])||isinsq(d[j].x2,d[j].y1,d[i]) ||isinsq(d[j].x1,d[j].y2,d[i])||isinsq(d[j].x2,d[j].y2,d[i])) return true; } else { int ni=i,nj=j; if(d[ni].att==2&&d[nj].att==1)swap(ni,nj); if(pd(d[nj].x1,d[nj].y1,d[nj].x1,d[nj].y2,d[ni].x1,d[ni].y1,d[ni].x2))return true; else if(pd(d[nj].x1,d[nj].y2,d[nj].x2,d[nj].y2,d[ni].x1,d[ni].y1,d[ni].x2))return true; else if(pd(d[nj].x2,d[nj].y2,d[nj].x2,d[nj].y1,d[ni].x1,d[ni].y1,d[ni].x2))return true; else if(pd(d[nj].x2,d[nj].y1,d[nj].x1,d[nj].y1,d[ni].x1,d[ni].y1,d[ni].x2))return true; } return false;}int main(){ scanf("%lld%lld%d",&x,&y,&n); for(int i=1;i<=n;++i){ int op;scanf("%d",&op); if(op==1){ long long x,y,r;scanf("%lld%lld%lld",&x,&y,&r); d[i].circle(x,y,r); } else { long long x1,y1,x2,y2; scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2); d[i].square(x1,y1,x2,y2); } } d[n+1].square(0,y,x,1ll<<60); d[n+2].square(0,-1ll<<60,1ll<<60,0); for(int i=1;i<=n;++i)addedge(i,i+n,1),addedge(i+n,i,1); for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) if(check(i,j)) addedge(i+n,j,1<<30),addedge(j+n,i,1<<30);bg=0,ed=n*2+1; for(int i=1;i<=n;++i)if(check(n+1,i))addedge(i+n,ed,1<<30); for(int i=1;i<=n;++i)if(check(n+2,i))addedge(bg,i,1<<30); int ans=0,f=0; while(bfs())while(f=find(bg,1<<30))ans+=f; printf("%d",ans); }
0 0
- BZOJ3630
- bzoj3630 镜面通道
- BZOJ3630: [JLOI2014]镜面通道
- bzoj3630: [JLOI2014]镜面通道
- bzoj3630 镜面通道 网络流
- BZOJ3630: [JLOI2014]镜面通道 最小割
- uva1151 Buy or Build
- STM32移植lwip之建立tcp服务器
- 预编译——关于#和##
- session还是cookie
- Android多线程下载服务器资源
- BZOJ3630
- Android6.0蓝牙探索旅程
- n个骰子的点数之和
- 这几条UI原则可以让你的设计提高(中)
- 头尾式动画
- 几种计算机视觉中常用的聚类算法(K-means, Agglomerative clustering, Mean shift, Spectral clustering)
- Scala 中的foreach和map方法比较
- Java持久层的三种查询方式
- MyBatis学习笔记