mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
Create 1311_蜘蛛侠.cpp
From http://www.acmerblog.com/hdu-3126-nova-4942.html
This commit is contained in:
parent
35f166b614
commit
01cf3f019b
201
QUSTOJ/1311_蜘蛛侠.cpp
Normal file
201
QUSTOJ/1311_蜘蛛侠.cpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* 解法: 很明显是几何 + 最小费用最大流, 关键是如何建图.
|
||||
* 1. 设置一个源点和汇点.
|
||||
* 2. 每个lich和每个wisp分别用一个点来表示.
|
||||
* 3. 如果第i个lich能攻击到第j个wisp, 那么在图中从lich[i]到wisp[j]增加一条边, 容量为1, 费用为0.
|
||||
* 4. 每个wisp连一条边到汇点, 容量为1, 费用为0.
|
||||
* 5. 源点到每个lich连k条边, k为每个lich能攻击到的wisp数量, 每条边的容量为1, 第i条边的费用为i * t (i为0 - k-1, t为lich的cooldown时间)
|
||||
* 运行最小费用最大流, 答案就是从源点到lich满流的边, 且费用最大的那条边的费用值.
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <math.h>
|
||||
using namespace std;
|
||||
const int maxn = 205;
|
||||
const double eps = 1e-8;
|
||||
typedef int typef;
|
||||
typedef int typec;
|
||||
#define inff 0x0fffffff
|
||||
#define infc 0x0fffffff
|
||||
#define V 500
|
||||
#define E 200000
|
||||
struct network
|
||||
{
|
||||
int nv, ne, pnt[E], nxt[E];
|
||||
int vis[V], que[V], head[V], pv[V], pe[V];
|
||||
typef flow, cap[E]; typec cost, dis[E], d[V];
|
||||
void addedge(int u, int v, typef c, typec w)
|
||||
{
|
||||
pnt[ne] = v; cap[ne] = c;
|
||||
dis[ne] = w; nxt[ne] = head[u]; head[u] = ne++;
|
||||
pnt[ne] = u; cap[ne] = 0;
|
||||
dis[ne] = -w; nxt[ne] = head[v]; head[v] = ne++;
|
||||
}
|
||||
int mincost(int src, int sink)
|
||||
{
|
||||
int i, k, f, r; typef mxf;
|
||||
for(flow = 0, cost = 0; ; )
|
||||
{
|
||||
memset(pv, -1, sizeof(pv));
|
||||
memset(vis, 0, sizeof(vis));
|
||||
for(i = 0; i < nv; ++i) d[i] = infc;
|
||||
d[src] = 0; pv[src] = src; vis[src] = 1;
|
||||
for(f = 0, r = 1, que[0] = src; r != f; )
|
||||
{
|
||||
i = que[f++]; vis[i] = 0;
|
||||
if(V == f) f = 0;
|
||||
for(k = head[i]; k != -1; k = nxt[k])
|
||||
if(cap[k] && dis[k]+d[i] < d[pnt[k]])
|
||||
{
|
||||
d[pnt[k]] = dis[k] + d[i];
|
||||
if(0 == vis[pnt[k]])
|
||||
{
|
||||
vis[pnt[k]] = 1;
|
||||
que[r++] = pnt[k];
|
||||
if(V == r) r = 0;
|
||||
}
|
||||
pv[pnt[k]] = i; pe[pnt[k]] = k;
|
||||
}
|
||||
}
|
||||
if(-1 == pv[sink]) break;
|
||||
for(k = sink, mxf = inff; k != src; k = pv[k])
|
||||
if(cap[pe[k]] < mxf) mxf = cap[pe[k]];
|
||||
flow += mxf; cost += d[sink] * mxf;
|
||||
for(k = sink; k != src; k = pv[k])
|
||||
{
|
||||
cap[pe[k]] -= mxf; cap[pe[k]^1] += mxf;
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
void init(int v)
|
||||
{
|
||||
nv = v; ne = 0;
|
||||
memset(head, -1, 4 * v);
|
||||
}
|
||||
} nw;
|
||||
struct Lich
|
||||
{
|
||||
double x, y, r;
|
||||
int t;
|
||||
void input()
|
||||
{
|
||||
scanf("%lf %lf %lf %d", &x, &y, &r, &t);
|
||||
}
|
||||
} lich[maxn];
|
||||
struct Wisp
|
||||
{
|
||||
double x, y;
|
||||
void input()
|
||||
{
|
||||
scanf("%lf %lf", &x, &y);
|
||||
}
|
||||
} wisp[maxn];
|
||||
struct Tree
|
||||
{
|
||||
double x, y, r;
|
||||
void input()
|
||||
{
|
||||
scanf("%lf %lf %lf", &x, &y, &r);
|
||||
}
|
||||
} tree[maxn];
|
||||
int T, N, M, K;
|
||||
int ecnt[maxn];
|
||||
double Dot(double dx1, double dy1, double dx2, double dy2)
|
||||
{
|
||||
return dx1 * dx2 + dy1 * dy2;
|
||||
}
|
||||
double Dis(double x0, double y0, double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double a, b, c;
|
||||
if (fabs(x1 - x2) > fabs(y1 - y2))
|
||||
{
|
||||
b = 1.0;
|
||||
a = b * (y2 - y1) / (x1 - x2);
|
||||
c = -(a * x1 + b * y1);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = 1.0;
|
||||
b = a * (x2 - x1) / (y1 - y2);
|
||||
c = -(a * x1 + b * y1);
|
||||
}
|
||||
return fabs(a * x0 + b * y0 + c) / sqrt(a * a + b * b);
|
||||
}
|
||||
bool NoCross(int a, int b)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < K; i++)
|
||||
{
|
||||
if (Dot(tree[i].x - lich[a].x, tree[i].y - lich[a].y, wisp[b].x - lich[a].x, wisp[b].y - lich[a].y) > 0.0 &&
|
||||
Dot(tree[i].x - wisp[b].x, tree[i].y - wisp[b].y, lich[a].x - wisp[b].x, lich[a].y - wisp[b].y) > 0.0 &&
|
||||
Dis(tree[i].x, tree[i].y, lich[a].x, lich[a].y, wisp[b].x, wisp[b].y) < tree[i].r + eps)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool InRound(int i, int j)
|
||||
{
|
||||
double dx = lich[i].x - wisp[j].x;
|
||||
double dy = lich[i].y - wisp[j].y;
|
||||
return sqrt(dx * dx + dy * dy) < lich[i].r + eps;
|
||||
}
|
||||
void BuildGraph()
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
ecnt[i] = 0;
|
||||
for (j = 0; j < M; j++)
|
||||
{
|
||||
if (InRound(i, j) && NoCross(i, j))
|
||||
{
|
||||
ecnt[i]++;
|
||||
nw.addedge(i, N + j, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
for (j = 0; j < ecnt[i]; j++)
|
||||
nw.addedge(N + M, i, 1, lich[i].t * j);
|
||||
}
|
||||
for (i = 0; i < M; i++)
|
||||
nw.addedge(N + i, N + M + 1, 1, 0);
|
||||
}
|
||||
void Solve()
|
||||
{
|
||||
nw.mincost(N + M, N + M + 1);
|
||||
if (nw.flow != M)
|
||||
{
|
||||
printf("-1\n");
|
||||
return;
|
||||
}
|
||||
int ans = 0;
|
||||
for (int p = nw.head[N+M]; p != -1; p = nw.nxt[p])
|
||||
{
|
||||
if (nw.cap[p] == 0 && nw.dis[p] > ans)
|
||||
ans = nw.dis[p];
|
||||
}
|
||||
printf("%d\n", ans);
|
||||
}
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
for (scanf("%d", &T); T; T--)
|
||||
{
|
||||
scanf("%d %d %d", &N, &M, &K);
|
||||
for (i = 0; i < N; i++)
|
||||
lich[i].input();
|
||||
for (i = 0; i < M; i++)
|
||||
wisp[i].input();
|
||||
for (i = 0; i < K; i++)
|
||||
tree[i].input();
|
||||
nw.init(N + M + 2);
|
||||
BuildGraph();
|
||||
Solve();
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user