您的位置:首页 > 其它

BZOJ3630: [JLOI2014]镜面通道

2017-01-23 21:43 375 查看

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

Sample Output

2

HINT

x<=100000,y<=1000,n<=300

 

Source

网络流
首先从上到下如果元件不连通光一定能过去
然后就是裸的最小割
这题难在建图,根本不用想,就是计算几何,写起来23333
判断圆和矩形相交我基本是抄的2333
#include<bits/stdc++.h>

using namespace std;

const int MAXN = 1110;
const int MAXM = 500050;
const int INF = 1e9 + 7;

int cnt = 1, n, m, ans, S, T, ql, qr;

int cur[MAXN], head[MAXN], q[MAXN], dis[MAXN];

struct edge
{
int to, nxt, flow;
}e[MAXM];

inline void add(int x, int y, int w) { e[ ++cnt ].to = y; e[ cnt ].nxt = head[ x ]; head[ x ] = cnt; e[ cnt ].flow = w; }
inline void addedge(int x, int y, int w) { add( x, y, w ); add( y, x, 0 ); }

inline bool bfs()
{
memset( dis, 0, sizeof dis ); ql = 0;
dis[ q[ qr = 1 ] = S ] = 1;
while( ql < qr )
{
int x = q[ ++ql ];
for( int i = head[ x ] ; i ; i = e[ i ].nxt )
if( e[ i ].flow&& !dis[ e[ i ].to ] )
dis[ q[ ++qr ] = e[ i ].to ] = dis[ x ] + 1;
}
return dis[ T ];
}

inline int dfs(int x, int flow)
{
if( x == T ) return flow;
int ret = 0;
for( int &i = cur[ x ] ; i ; i = e[ i ].nxt )
if( e[ i ].flow && dis[ e[ i ].to ] == dis[ x ] + 1 )
{
int d = dfs( e[ i ].to, min( flow - ret, e[ i ].flow ) );
e[ i ].flow -= d;
e[ i ^ 1 ].flow += d;
ret += d;
if( ret == flow )
return flow;
}
if( !ret ) dis[ x ] = -1;
return ret;
}

inline void dinic()
{
while( bfs() )
memcpy( cur, head, sizeof cur ),
ans += dfs( S, INF );
}

inline int read()
{
int sc = 0, f = 1; char ch = getchar();
while( ch < '0' || ch > '9' ) { if( ch == '-' ) f = -1; ch = getchar(); }
while( ch >= '0' && ch <= '9' ) sc = sc * 10 + ch - '0', ch = getchar();
return sc * f;
}

struct object
{
int type, x1, y1, x2, y2, r;
inline void scan()
{
type = read();
if( type == 1 ) x1 = read(), y1 = read(), r = read();
else x1 = read(), y1 = read(), x2 = read(), y2 = read();
}
}a[MAXN];

int x, y;

inline double sqr(double x) { return x * x; }
inline double dist(int x1, int y1, int x2, int y2) { return sqrt( sqr( x2 - x1 ) + sqr( y2 - y1 ) ); }

inline bool cross(int p, int q)
{
if( a[ p ].type == 1 && a[ q ].type == 2 ) return cross( q, p );
if( a[ p ].type == 1 && a[ q ].type == 1 ) { return dist( a[ p ].x1, a[ p ].y1, a[ q ].x1, a[ q ].y1 ) <= a[ p ].r + a[ q ].r; }
if( a[ p ].type == 2 && a[ q ].type == 2 ) { return ( max( a[ p ].x1, a[ q ].x1 ) <= min( a[ p ].x2, a[ q ].x2 ) ) && ( max( a[ p ].y1, a[ q ].y1 ) <= min( a[ p ].y2, a[ q ].y2 ) ); }
int x1 = a[ p ].x1, y1 = a[ p ].y1, x2 = a[ p ].x2, y2 = a[ p ].y2;
int x = a[ q ].x1, y = a[ q ].y1, r = a[ q ].r;
if( dist( x, y, x1, y1 ) <= r || dist( x, y, x2, y2 ) <= r || dist( x, y, x1, y2 ) <= r || dist( x, y, x2, y1 ) <= r ) return true;
if( x >= x1 && x <= x2 && ( abs( y - y1 ) <= r || abs( y - y2 ) <= r ) ) return true;
if( y >= y1 && y <= y2 && ( abs( x - x1 ) <= r || abs( x - x2 ) <= r ) ) return true;
return false;
}

int main()
{
x = read(); y = read(); n = read(); T = 1;
for( int i = 1 ; i <= n ; i++ )
{
a[ i ].scan();
addedge( i << 1, i << 1 | 1, 1 );
for( int j = 1 ; j < i ; j++ ) if( cross( i, j ) ) addedge( i << 1 | 1, j << 1, INF ), addedge( j << 1 | 1, i << 1, INF );
if( a[ i ].type == 1 )
{
if( a[ i ].y1 - a[ i ].r <= 0 ) addedge( S, i << 1, INF );
if( a[ i ].y1 + a[ i ].r >= y ) addedge( i << 1 | 1, T, INF );
}
else
{
if( a[ i ].y1 <= 0 ) addedge( S, i << 1, INF );
if( a[ i ].y2 >= y ) addedge( i << 1 | 1, T, INF );
}
}
dinic();
return printf( "%d\n", ans ), 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: