zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    QOMO Linux 4.0 正式版发布
    LinkChecker 8.1 发布,网页链接检查
    pgBadger 2.1 发布,PG 日志分析
    Aletheia 0.1.1 发布,HTTP 调试工具
    Teiid 8.2 Beta1 发布,数据虚拟化系统
    zLogFabric 2.2 发布,集中式日志存储系统
    开源电子工作套件 Arduino Start Kit 登场
    Piwik 1.9 发布,网站访问统计系统
    Ruby 1.9.3p286 发布,安全修复版本
    toBraille 1.1.2 发布,Java 盲文库
  • 原文地址:https://www.cnblogs.com/yours1103/p/3470257.html
Copyright © 2011-2022 走看看