bzoj1822: [JSOI2010]Frozen Nova 冷冻波

Problem 1822. -- [JSOI2010]Frozen Nova 冷冻波

1822: [JSOI2010]Frozen Nova 冷冻波

Time Limit: 10 Sec   Memory Limit: 64 MB
Submit: 2355   Solved: 768
[ Submit][ Status][ Discuss]

Description

WJJ喜欢“魔兽争霸”这个游戏。在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵。我们认为,巫妖和小精灵都可以看成是平面上的点。 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵。 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放。不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以杀死一个小精灵。 现在巫妖的头目想知道,若从0时刻开始计算,至少需要花费多少时间,可以杀死所有的小精灵?

Input

输入文件第一行包含三个整数N、M、K(N,M,K<=200),分别代表巫妖的数量、小精灵的数量和树木的数量。 接下来N行,每行包含四个整数x, y, r, t,分别代表了每个巫妖的坐标、攻击范围和施法间隔(单位为秒)。 再接下来M行,每行两个整数x, y,分别代表了每个小精灵的坐标。 再接下来K行,每行三个整数x, y, r,分别代表了每个树木的坐标。 输入数据中所有坐标范围绝对值不超过10000,半径和施法间隔不超过20000。

Output

输出一行,为消灭所有小精灵的最短时间(以秒计算)。如果永远无法消灭所有的小精灵,则输出-1。

Sample Input

2 3 1
-100 0 100 3
100 0 100 5
-100 -10
100 10
110 11
5 5 10

Sample Output

5

HINT

Source

JSOI2010第二轮Contest1

[ Submit][ Status][ Discuss]

HOME Back

其实我只想打个网络流,但莫名其妙开始打计算几何

网络流部分比较简单,二分时间,这样每个巫妖的伤害数量上限已经确定了
S向巫妖连 t i m e t i + 1 \frac{time}{t_i}+1 titime+1边,巫妖向可以打到的精灵连1边,精灵向T连1边
判断最大流是否为精灵数就可以了

然后就是判断圆是否和线段有交
圆到线段的距离是 叉 积 线 段 长 度 \frac{叉积}{线段长度} 线,因为叉积可以看成围成的平行四边形的面积
如果圆到线段的点不在线段上,这样点积为负,这时只需判断是否会覆盖端点就可以了


#include 
#include 
#include 
#include 
#include 
using namespace std;

#define dd c=getchar()
int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd
void write(int x) {if (x<0) putchar('-'),x=-x;if (x>=10) write(x/10);putchar(x%10|'0');}
void wln(int x) {write(x);putchar('\n');}void wsp(int x) {write(x);putchar(' ');}

const int N = 205;

struct node {
	double x,y;
}a[N],b[N],c[N];
node operator -(node a, node b) {return (node) {a.x-b.x, a.y-b.y};}
double operator *(node a, node b) {return a.x*b.x+a.y*b.y;}
double operator ^(node a, node b) {return a.x*b.y-a.y*b.x;}
double sqr(int x) {return x*x;}
double dis(node a, node b) {return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
struct edge {
	int t, nxt, w;
}e[N*N*5];
int n,m,K,cnt,S,T;
int r[N],r2[N],t[N],vis[N][N];
int head[N<<1],dep[N<<1], cur[N<<1];
queue<int> q;
void add(int u, int t, int w) {
	e[++cnt] = (edge) {t, head[u], w}; head[u] = cnt;
	e[++cnt] = (edge) {u, head[t], 0}; head[t] = cnt;
}

void build(int x) {
	memset(head, 0, sizeof head); cnt = 1;
	for (int i = 1; i <= n; i++) add(S, i, x/t[i]+1);
	for (int i = 1; i <= m; i++) add(i+n, T, 1);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) if (vis[i][j]) add(i, j+n, 1);
}

bool bfs() {
    memset(dep, 0, sizeof dep);
    dep[S] = 1; q.push(S);
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = head[u]; i; i = e[i].nxt) {
            int t = e[i].t;
            if (!dep[t] && e[i].w) dep[t] = dep[u]+1, q.push(t);
        }
    }
    return dep[T] != 0;
}
int dfs(int x, int flow) {
    if (x == T) return flow;
    for (int &i = cur[x]; i; i = e[i].nxt) {
        int t = e[i].t;
        if (e[i].w > 0 && dep[t] == dep[x]+1) {
            int tmp = dfs(t, min(flow, e[i].w));
            if (tmp <= 0) continue;
            e[i].w-=tmp; e[i^1].w+=tmp;
            return tmp;
        }
    }
    return 0;
}
int dinic() {
    int ans = 0;
    while (bfs()) {
        for (int i = 1; i <= T; i++) cur[i] = head[i];
        while (int k = dfs(S, 1e9)) ans+=k;
    }
    return ans;
}
int main() {
//	freopen("1822.in", "r", stdin);
//	freopen("1822.out", "w", stdout);
	n = read(); m = read(); K = read();
	S = n+m+1; T = S+1;
	for (int i = 1; i <= n; i++) a[i].x = read(), a[i].y = read(), r[i] = read(), t[i] = read();
	for (int i = 1; i <= m; i++) b[i].x = read(), b[i].y = read();
	for (int i = 1; i <= K; i++) c[i].x = read(), c[i].y = read(), r2[i] = read();
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			if (dis(a[i], b[j]) > r[i]) continue;
			vis[i][j] = 1;
			for (int k = 1; k <= K; k++) {
				if ((c[k]-a[i])*(b[j]-a[i]) < 0) && dis(a[i], c[k]) >= r2[k]) continue; 
				if ((c[k]-b[j])*(a[i]-b[j]) < 0 && dis(b[j], c[k]) >= r2[k]) continue;
				if (fabs((c[k]-a[i])^(c[k]-b[j]))/dis(a[i], b[j]) >= r2[k]) continue;
				vis[i][j] = 0; break;
			}
	}
	int l = 0, r = 4e6+7, ans=-1;
	while (l <= r) {
		int mid = (l+r)>>1;
		build(mid);
		if (dinic() == m) r = mid-1, ans = mid;
		else l = mid+1;
	}
	wln(ans);
}

你可能感兴趣的:(最大流,计算几何)