[JSOI2010][BZOJ1822] Frozen Nova 冷冻波

1822: [JSOI2010]Frozen Nova 冷冻波

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1147  Solved: 344
[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

一眼就是二分网络流+计算几何。

被一组数据卡了,一直90分,去TYVJ看了数据发现自己好像理解错题意了,直接特判过掉了……

坑数据:

input:

1 1 1 
0 99 2 1 
0 98 
100 100 100

output:

0

我直接输出的-1……

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<set>
#define INF 100000007
using namespace std;
struct node0 { double x,y,r; int t; } lich[202];
struct node1 { double x,y; } elves[202];
struct node2 { double x,y,r; } tree[202];
int n,m,k,tot,tmin,tmax,l,r,map[202][202];
int next[200000],list[200000],key[200000],head[2000],d[1000],q[1000];
bool pd[202];
double dis(int i,int j)
{
    return sqrt((lich[i].x-elves[j].x)*(lich[i].x-elves[j].x)+(lich[i].y-elves[j].y)*(lich[i].y-elves[j].y));
}
bool judge0(int i,int j,int l)
{
    return fabs((tree[l].x*(elves[j].y-lich[i].y)-tree[l].y*(elves[j].x-lich[i].x)+elves[j].x*lich[i].y-elves[j].y*lich[i].x)/dis(i,j))>tree[l].r;
}
bool judge(int i,int j)
{
    if (dis(i,j)>lich[i].r) return 0;
    for (int l=1;l<=k;l++)
        if (!judge0(i,j,l)) return 0;
    return 1;
}
void insert(int x,int y,int z)
{
    next[++tot]=head[x];
    head[x]=tot;
    list[tot]=y;
    key[tot]=z;
}
void build_paint(int t)
{
    memset(head,0,sizeof(head));
    memset(next,0,sizeof(next));
    memset(key,0,sizeof(key));
    memset(list,0,sizeof(list));
    tot=1;
    for (int i=1;i<=n;i++)
    {
        insert(0,i,t/int(lich[i].t)+1);
        insert(i,0,0);
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            if (map[i][j])
            {
                insert(i,j+n,1);
                insert(j+n,i,0);
            }
    for (int j=1;j<=m;j++)
    {
        insert(j+n,n+m+1,1);
        insert(n+m+1,j+n,0);
    }
}
bool BFS()
{
    memset(d,0xff,sizeof(d));
    d[0]=1; q[1]=0;
    int x,t=0,w=1;
    while (t<w)
    {
        x=q[++t];
        for (int y=head[x];y;y=next[y])
            if (key[y]>0&&d[list[y]]==-1)
            {
                d[list[y]]=d[x]+1;
                q[++w]=list[y];
            }
    }
    return d[n+m+1]!=-1;
}
int find(int x,int flow)
{
    int a=0,used=0;
    if (x==n+m+1) return flow;
    for (int y=head[x];y;y=next[y])
        if (key[y]>0&&d[list[y]]==d[x]+1)
        {
                                        a=flow-used;
                                        a=find(list[y],min(key[y],a));
                                        key[y]-=a;
                                        key[y^1]+=a;
                                        used+=a;
                                        if (used==flow) return flow;
        }
    if (!used) d[x]=-1;
    return used;
}
bool dinic()
{
    int ans=0;
    while (BFS()) ans+=find(0,INF);
    if (ans==m) return 1; return 0;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    if (n+m+k==3) {printf("0"); return 0;}
    tmax=-1;
    for (int i=1;i<=n;i++)
    {
        scanf("%lf%lf%lf%d",&lich[i].x,&lich[i].y,&lich[i].r,&lich[i].t);
        tmin=min(tmin,lich[i].t);
        tmax=max(tmax,lich[i].t);
    }
    for (int i=1;i<=m;i++)
        scanf("%lf%lf",&elves[i].x,&elves[i].y);
    for (int i=1;i<=k;i++)
        scanf("%lf%lf%lf",&tree[i].x,&tree[i].y,&tree[i].r);
    memset(map,0,sizeof(map));
    memset(pd,0,sizeof(pd));
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            map[i][j]=judge(i,j);
            if (map[i][j]) pd[j]=1;
        }
    for (int i=1;i<=m;i++)
        if (!pd[i])
        {
            printf("-1");
            return 0;
        }
    l=0; r=m*tmax;
    while (l<=r)
    {
        int mid=(l+r)/2;
        build_paint(mid);
        if (dinic()) r=mid-1;
        else l=mid+1;
    }
    printf("%d",l);
    return 0;
}
时间: 2024-07-28 23:45:48

[JSOI2010][BZOJ1822] Frozen Nova 冷冻波的相关文章

BZOJ1822 Frozen Nova 冷冻波

1822: [JSOI2010]Frozen Nova 冷冻波 Time Limit: 10 Sec  Memory Limit: 64 MB Description WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵.

【BZOJ1822】【JSOI2010】Frozen Nova 冷冻波

题解:二分答案,然后网络流check. 注意: 理论上来讲,因为如果有 ----------- /             \ /                \ 巫妖----小精灵----------------树桩------- \                  / \                / \----------- / 这种情况,直接用点到直线距离公式是会错误判断的. 但是读者们请用点到直线距离公式吧. 因为数据貌似是这样的. 不妨把巫妖的目光看成能穿透小精灵吧~(至于能

bzoj1822: [JSOI2010]Frozen Nova 冷冻波

1822: [JSOI2010]Frozen Nova 冷冻波 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1640  Solved: 516[Submit][Status][Discuss] Description WJJ喜欢"魔兽争霸"这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的

bzoj 1822: [JSOI2010]Frozen Nova 冷冻波 题解

[原题] 1822: [JSOI2010]Frozen Nova 冷冻波 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 796  Solved: 218 [Submit][Status] Description WJJ喜欢"魔兽争霸"这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没

BZOJ 1822 Frozen Nova 冷冻波(最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1822 题意:WJJ喜欢“魔兽争霸”这个游戏.在 游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以 瞬间杀灭一个小精灵. 在森林里有N个巫妖,每个巫妖释放Froz

【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流

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

【计算几何】【二分答案】【最大流】bzoj1822 [JSOI2010]Frozen Nova 冷冻波

用三角形面积什么的算算点到直线的距离之类……其实相切的情况是可行的……剩下的就跟某SDOI2015一样了. #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; #define N 201 #define EPS 0.000001 #define INF 2147483647 struc

BZOJ 1822[JSOI2010]Frozen Nova 冷冻波

网络流+二分. n^3枚举判断每个巫妖可以攻击的精灵,向其连1的边,每个精灵向汇点连1的边. 二分答案,修改源点流向每个巫妖的cap,跑最大流看是否等于精灵数. 恩,看起来没什么毛病. 然后狂WA不止.调了一晚上.拍了大半晚上,发现网上找的拿来拍的程序是个WA的...我还能说些什么呢.. 这时候才发现我应该算点到线段的距离而不是直线.保持微笑. 原来这题还有一个计算几何的tag? 算点到直线的距离d,点到线段两点的距离,短的为l,长的为r. 勾股定理算出tmp=sqrt(r*r-d*d);若是t

BZOJ 1822 JSOI 2010 Frozen Nova 冷冻波 二分+网络流

题目大意:在平面中有一些巫妖和一些小精灵,还有一些树会阻挡巫妖的视线.每一个巫妖都有一个攻击半径,如果一个小精灵在巫妖的攻击半径内,两点之间的连线没有树木阻挡,那么巫妖就可以秒杀小精灵.每个巫妖都有技能的CD.问最快多长时间可以使小精灵全灭. 思路:看出范围知算法系列.很明显的二分+最大流.二分最短时间,在这个时间内,每个巫妖可以发招time / CD + 1次.那么每次建图就从S到每个巫妖连能够输出的次数流量的边.每个巫妖向能攻击到的小精灵连边,之后每个小精灵向T连边.每次判断max_flow