• csuoj 1355: 地雷清除计划


    这是一个非常神奇的题;

    感觉像一个模拟搜索;

    但是竟然可以用网络流来解决;

    直接粘题解把:

      如果不能走通的话,必然说明能够从右上角(图外面)沿雷“跳” ,一直可以“跳”左
    下角(图外面) ,因此建好图之后求一个最小割就可以得到结果了。但是关键在于:1.哪些
    雷之间可以相互“跳” ?2.哪些雷可以从右上角“跳”过去,哪些雷可以“跳”到左下角?
      第二个问题很好办,如果地雷的范围能接触到最上或者最右的格子,就可以从右上角跳
    到这个雷上,如果地雷的范围能接触到最下或者最右的格子,就可以跳到左下角。
      第一个问题需要分类讨论一下,如果两个雷在同一水平线或者竖直线上,当两个雷的距
    离不超过 2*K+1 时可以认为两个雷是连通的,但如果不在同一水平线或者竖直线上时,当
    两个雷的距离不超过 2*K+2 时可以认为两个雷是连通的。

    注意雷要拆点,容量为 1,其他边容量为 INF

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define maxn 1550
    #define maxm 40009
    #define inf 9999999
    using namespace std;
     
    struct edge
    {
        int from,to,cap,flow;
        edge() {}
        edge(int from,int to,int cap,int flow)
            :from(from),to(to),cap(cap),flow(flow) {}
    };
     
    struct dinic
    {
        int n,m,s,t;
        edge edges[maxm*2];
        int head[maxn];
        int next[maxm*2];
        bool inq[maxn];
        int d[maxn];
        int cur[maxn];
        void init(int n)
        {
            this->n=n;
            m=0;
            memset(head,-1,sizeof(head[0])*(n+1));
        }
     
        void addedge(int from,int to,int cap)
        {
            next[m]=head[from];
            edges[m]=edge(from,to,cap,0);
            head[from]=m++;
            next[m]=head[to];
            edges[m]=edge(to,from,0,0);
            head[to]=m++;
        }
        bool bfs()
        {
            memset(inq,0,sizeof(inq[0])*(n+1));
            queue<int>q;
            q.push(s);
            d[s]=0;
            inq[s]=1;
            while(!q.empty())
            {
                int u=q.front();
                q.pop();
                for(int i=head[u]; i!=-1; i=next[i])
                {
                    edge& e=edges[i];
                    int v=e.to;
                    if(!inq[v]&&e.cap>e.flow)
                    {
                        inq[v]=1;
                        d[v]=d[u]+1;
                        q.push(v);
                        if(v==t)return 1;
                    }
                }
            }
            return 0;
        }
        int dfs(int u,int a)
        {
            if(u==t||a==0)return a;
            int flow=0,f;
            for(int&i=cur[u]; i!=-1; i=next[i])
            {
                edge& e=edges[i];
                int v=e.to;
                if(d[u]+1==d[v]&&(f=dfs(v,min(a,e.cap-e.flow)))>0)
                {
                    e.flow+=f;
                    edges[i^1].flow-=f;
                    flow+=f;
                    a-=f;
                    if(a==0)break;
                }
            }
            return flow;
        }
        int maxflow(int s,int t)
        {
            this->s=s;
            this->t=t;
            int flow=0;
            while(bfs())
            {
                memcpy(cur,head,sizeof(head[0])*(n+1));
                flow+=dfs(s,inf);
            }
            return flow;
        }
    };
     
    dinic solve;
     
    struct node
    {
        int x,y;
    } no[maxn];
    char s[100];
    int main()
    {
    //    freopen("test0.in","r",stdin);
        int t;
        int n,m,d;
        scanf("%d",&t);
        while(t--)
        {
            int cnt=1;
            scanf("%d%d%d",&n,&m,&d);
            for(int i=1; i<=n; i++)
            {
                scanf("%s",s+1);
                for(int j=1; j<=m; j++)
                {
                    if(s[j]=='*')
                    {
                        no[cnt].x=i;
                        no[cnt++].y=j;
                    }
                }
            }
            int sr=0;
            int tr=2*cnt+1;
            solve.init(2*cnt+2);
            for(int i=1; i<cnt; i++)
            {
                solve.addedge(2*i,2*i+1,1);
                if((no[i].x-1)<=d||((m-no[i].y)<=d))
                    solve.addedge(sr,2*i,inf-1);
                if((n-no[i].x)<=d||(no[i].y-1)<=d)
                    solve.addedge(2*i+1,tr,inf-1);
            }
            for(int i=1; i<cnt; i++)
                for(int j=1; j<cnt; j++)
                {
                    int dis=abs(no[i].x-no[j].x)+abs(no[i].y-no[j].y);
                    if(no[i].x==no[j].x||no[i].y==no[j].y)
                    {
                        if(dis<=2*d+1)
                            solve.addedge(2*i+1,2*j,inf-1);
                    }
                    else
                    {
                        if(dis<=2*d+2)
                            solve.addedge(2*i+1,2*j,inf-1);
                    }
                }
            printf("%d
    ",solve.maxflow(sr,tr));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    LocalDate、LocalTime、LocalDateTime示例
    Instant时间戳示例
    Mybatis面试题
    SpringMVC面试题
    Spring面试题
    redis面试题
    计算机网络面试题
    java集合面试题
    java基础面试题
    MySQL面试题汇总
  • 原文地址:https://www.cnblogs.com/yours1103/p/3470257.html
Copyright © 2020-2023  润新知