• BZOJ1340: [Baltic2007]Escape逃跑问题


    Description

    战犯们企图逃离监狱,他们详细地计划了如何逃出监狱本身,逃出监狱之后他们希望在附近的一个村子里找到掩护。村子(下图中的B)和监狱(图中的A)中间有一个峡谷,这个峡谷也是有士兵守卫的。守卫峡谷的士兵们坐在岗哨上很少走动,每个士兵的观察范围是100米。士兵所处位置决定了战犯们能否安全通过峡谷,安全通过的条件就是在任何时刻战犯们距离最近的士兵大于100米。 给定峡谷的长、宽和每个士兵在峡谷中的坐标,假定士兵的位置一直保持不变,请你写一个程序计算战犯们能否不被士兵发现,顺利通过峡谷。如果不能,那么战犯们最少需要消灭几个士兵才能安全通过峡谷(无论士兵是否被另一个士兵看到,他都可以被消灭)。 

    Input

    第一行有三个整数L、W和N,分别表示峡谷的长度、宽度和士兵的人数。接下来的N行,每行两个整数Xi和Yi,表示第i个士兵在峡谷的坐标(0 <= Xi <= L, 0 <= Yi <= W),坐标以米为单位,峡谷的西南角坐标为(0, 0),东北角坐标为(L, W),见上图。注意:通过峡谷可以从(0, ys)(0 <= ys <= W)到(L, ye)(0 <= ye <= W),其中ys, ye不一定是整数。

    Output

    只有一行,为一个整数,即安全通过峡谷需要消灭的士兵的人数,如果不需要消灭任何士兵,则输出0。

    Sample Input

    130 340 5
    10 50
    130 130
    70 170
    0 180
    60 260

    Sample Output

    1

    HINT

    1 <= W <= 50,000 1 <= L <= 50,000 1 <= N <= 250

    考虑题目的限制
    被挡住就说明首尾相接的圆堵住了,如下图:

    就跟NOIP2017年那个题一样,删去最少的圆使上下两边界不连通

    代码如下:

    //MT_LI
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<ctime>
    #include<map>
    #include<bitset>
    #include<set>
    #define ll long long
    #define mp(x,y) make_pair(x,y)
    #define pll pair<long long,long long>
    #define pii pair<int,int>
    using namespace std;
    inline ll read()
    {
        ll f=1,x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int stack[20];
    inline void write(int x)
    {
        if(x<0){putchar('-');x=-x;}
        if(!x){putchar('0');return;}
        int top=0;
        while(x)stack[++top]=x%10,x/=10;
        while(top)putchar(stack[top--]+'0');
    }
    inline void pr1(int x){write(x);putchar(' ');}
    inline void pr2(int x){write(x);putchar('
    ');}
    struct dicnic{
        int x,y,c,next,other;
    }a[2100000];int len,last[1100];
    void ins(int x,int y,int c)
    {
        a[++len]=(dicnic){x,y,c,last[x],len+1},last[x]=len;
        a[++len]=(dicnic){y,x,0,last[y],len-1},last[y]=len;
    }
    int h[1100],head,tail;
    int st,ed,list[1100];
    bool bt_h()
    {
        memset(h,0,sizeof(h));h[st]=1;
        head=1,tail=2;list[1]=st;
        while(head!=tail)
        {
            int x=list[head];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(h[y]==0&&a[k].c)
                {
                    h[y]=h[x]+1;
                    list[tail++]=y;
                }
            }
            head++;
        }
        if(h[ed])return true;
        return false;
    }
    int findflow(int x,int f)
    {
        if(x==ed)return f;
        int s=0,t;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(h[y]==h[x]+1&&a[k].c&&s<f)
            {
                s+=(t=findflow(y,min(a[k].c,f-s)));
                a[k].c-=t;a[a[k].other].c+=t;
            }
        }
        if(s==0)h[x]=0;
        return s;
    }
    int L,W,n;
    struct node{
        ll x,y;
    }e[260];
    ll S(ll x){return x*x;}
    int main()
    {
        L=read(),W=read(),n=read();st=0,ed=2*n+1;
        memset(last,0,sizeof(last));len=0;
        for(int i=1;i<=n;i++)
        {
            e[i].x=read(),e[i].y=read();
            if(e[i].y<=100)ins(st,i,1);
            if(e[i].y>=W-100)ins(i+n,ed,1);
            ins(i,i+n,1);
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j)
                    if(S(e[i].x-e[j].x)+S(e[i].y-e[j].y)<=40000)
                        ins(i+n,j,1);
        int ans=0;
        while(bt_h())ans+=findflow(st,1<<30);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    HDOJ 1556 线段树
    POJ 3977 折半枚举
    2017ACM省赛选拔赛题解
    关于四舍五入和截断
    POJ 3422 最小费用最大流
    Codeforces Round #407 (Div. 2) D. Weird journey 思维+欧拉
    POJ 3155 最大密度子图
    无向图最小割 stoer_wagner算法
    最大权闭合子图
    L2-001. 紧急救援 Dijkstra
  • 原文地址:https://www.cnblogs.com/MT-LI/p/10808415.html
Copyright © 2020-2023  润新知