zoukankan      html  css  js  c++  java
  • bzoj1822

    1822: [JSOI2010]Frozen Nova 冷冻波

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

     

     

    思路很简单的。每个witch向他能攻击到的精灵连一条容量1的边,每个精灵向T连容量1的边。

    二分时间,得到witch的攻击次数。S向每个witch连接容量为攻击次数的边,判断最大流是不是=精灵个数

     

    但是,,这道题的连边判断很蛋疼,要用很多几何知识。

     

    代码写错了一些地方,懒得调了,先挂上

    /*
    爆炸
    不想调了 
    */
    
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #define inf 0x3f3f3f3f
    #define ll long long
    #define N 405
    using namespace std;
    int n,m,K,tot,S,T,pre,phd[N],hd[N],d[N],cur[N],vis[N];
    struct witch{int x,y,r,t;}t[N];
    struct ghost{int x,y;}p[N];
    struct tree{int x,y,r;}tr[N];
    struct edge{int v,next,cap;}e[N*N*2];
    void adde(int u,int v,int c){
        e[tot].v=v;
        e[tot].next=hd[u];
        e[tot].cap=c;
        hd[u]=tot++;
    }
    bool bfs(){
        queue<int>q;
        memset(vis,0,sizeof(vis));
        d[S]=0;vis[S]=1;q.push(S);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=hd[u];~i;i=e[i].next){
                int v=e[i].v;
                if(e[i].cap&&!vis[v]){
                    vis[v]=1;
                    d[v]=d[u]+1;
                    q.push(v);
                }
            }
        }
        return vis[T];
    }
    int dfs(int u,int a){
        if(u==T||!a)return a;
        int fl=0,f;
        for(int &i=cur[u];~i;i=e[i].next){
            int v=e[i].v;
            if(e[i].cap&&d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap,a)))){
                fl+=f;a-=f;e[i].cap-=f;
                e[i^1].cap+=f;if(!a)break;
            }
        }
        return fl;
    }
    
    int dinic(){
        int flow=0;
        while(bfs()){
            for(int i=S;i<=T;i++)cur[i]=hd[i];
            flow+=dfs(S,inf);
        }
        return flow;
    }
    int calc(int i,int j)
    {return (p[j].x-t[i].x)*(p[j].x-t[i].x)+(p[j].y-t[i].y)*(p[j].y-t[i].y);}
    
    struct vec{
        int x,y;
        vec res(){
            vec a=*this;
            a.x=-a.x;
            a.y=-a.y;
            return a;
        }
    };
    int dj(vec a,vec b){return a.x*b.x+a.y*b.y;}
    int cj(vec a,vec b){return abs(a.x*b.y-b.x*a.y);}
    bool check(int i,int j){
        for(int k=1;k<=K;k++){
            vec a=(vec){tr[k].x-t[i].x,tr[k].y-t[i].y};
            vec b=(vec){p[j].x-t[i].x,p[j].y-t[i].y};
            int sq=cj(a,b);
            double d=sqrt(calc(i,j));
            double h=sq/d/2;
            if(h>tr[k].r)continue;
            if(dj(a,b)<=0)continue;
            a=(vec){tr[k].x-p[j].x,tr[k].y-p[j].y};
            b=b.res();
            if(dj(a,b)>0)return 0;
        }
        return 1;
    }
    
    bool judge(int x){
        int sum=0;
        for(int i=0;i<tot;i++){
            if(i<pre){
                if(i&1)e[i].cap=0;
                else e[i].cap=1;
            }
            else{
                int id=(i-pre+1)/2+1;
                if(i&1)e[i].cap=0;
                else e[i].cap=x/t[id].t+1,sum+=x/t[id].t+1;
            }
        }
        if(sum<m)return 0;
        int flow=dinic();
        return flow==m;
    }
    
    int main(){
    #ifdef wsy
        freopen("data.in","r",stdin);
    #else
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
    #endif
        memset(hd,-1,sizeof(hd));
        scanf("%d%d%d",&n,&m,&K);
        S=0;T=n+m+1;int mxt;
        for(int i=1;i<=n;i++)
        scanf("%d%d%d%d",&t[i].x,&t[i].y,&t[i].r,&t[i].t),mxt=max(mxt,t[i].t);
        for(int i=1;i<=m;i++)
        scanf("%d%d",&p[i].x,&p[i].y);
        for(int i=1;i<=K;i++)
        scanf("%d%d%d",&tr[i].x,&tr[i].y,&tr[i].r);
        int fg=0;
        for(int i=1;i<=m&&!fg;i++)
        for(int j=1;j<=K&&!fg;j++){
            int d=(p[i].x-tr[j].x)*(p[i].x-tr[j].x)+(p[i].y-tr[j].y)*(p[i].y-tr[j].y);
            if(d<=tr[j].r*tr[j].r)fg=1;
        }
        if(fg){puts("-1");return 0;}
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            int dis=calc(i,j);
            if(dis>t[i].r*t[i].r||!check(i,j))continue;
            adde(i,j+n,1);adde(j+n,i,0);//printf("%d %d %d
    ",i,j+n,1);
        }
        for(int i=1;i<=m;i++)adde(i+n,T,1),adde(T,i+n,0)/*,printf("%d %d %d
    ",i+n,T,1)*/;
        pre=tot;for(int i=1;i<=n;i++)adde(S,i,0),adde(i,S,0);
        int l=0,r=mxt*m,ans=-1;
        while(l<=r){
            int mid=l+r>>1;
            if(judge(mid)){
                r=mid-1;
                ans=mid;
            }
            else l=mid+1;
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    获取小程序码
    获取目标地与当前地距离
    小程序图片预览
    地图导航
    Jquery无缝滚动
    短信验证
    根据经纬度获取地址
    微信小程序中使用emoji表情
    小程序图片上传
    地球人类的牢笼
  • 原文地址:https://www.cnblogs.com/wsy01/p/7927115.html
Copyright © 2011-2022 走看看