zoukankan      html  css  js  c++  java
  • bzoj 4930: 棋盘

    Description

    给定一个n×n的棋盘,棋盘上每个位置要么为空要么为障碍。定义棋盘上两个位置(x,y),(u,v)能互相攻击当前仅
    当满足以下两个条件:
    1:x=u或y=v
    2:对于(x,y)与(u,v)之间的所有位置,均不是障碍。
    现在有q个询问,每个询问给定ki,要求从棋盘中选出ki个空位置来放棋子,问最少互相能攻击到的棋子对数是多少?

    Input

    第一行一个整数n。
    接下来输入一个n×n的字符矩阵,一个位置若为.,则表示这是一个空位置,若为#,则为障碍。
    第n+2行输入一个整数q代表询问个数。
    接下来q行,每行一个整数k,代表要放的棋子个数。
    n ≤ 50, q ≤ 10000, k ≤ 棋盘中空位置数量

    Output

    输出共q行,每行代表对应询问的最少的互相能攻击到的棋子对数。
    不难得出费用流的模型,由于图的特殊性可用bfs求最小费用增广路
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    const int inf=0x3f3f3f3f;
    int n,q,id[55][55][2],id1=0,id2=0,as[2507],ap=0,d[5007],l[5007];
    char s[55][55];
    int es[5007],enx[5007],ev[5007],e0[5007],ep=2,lt;
    void ae(int a,int b){
        es[ep]=b;enx[ep]=e0[a];ev[ep]=1;e0[a]=ep++;
        es[ep]=a;enx[ep]=e0[b];ev[ep]=0;e0[b]=ep++;
    }
    bool cmp(int a,int b){
        return d[a]<d[b];
    }
    int q0[5007],ed[5007],tk=1;
    std::queue<int>q1;
    void mins(int&a,int b){if(a>b)a=b;}
    void cal(int w){
        if(w>id1)mins(lt,l[w]+d[w]);
        for(int i=e0[w];i;i=enx[i])if(ev[i]){
            int u=es[i];
            if(l[u]>l[w])l[u]=l[w],q1.push(u);
        }
    }
    int dfs(int w){
        if(ed[w]==tk)return 0;
        ed[w]=tk;
        if(w>id1&&l[w]+d[w]==lt){
            ++d[w];
            return 1;
        }
        for(int i=e0[w];i;i=enx[i])if(ev[i]&&l[es[i]]==l[w]&&dfs(es[i])){
            ev[i]=0,ev[i^1]=1;
            return 1;
        }
        return 0;
    }
    bool cal(){
        lt=inf;
        for(int i=1;i<=id1;++i)q0[i]=i,l[i]=d[i];
        for(int i=id1+1;i<=id2;++i)l[i]=inf;
        std::sort(q0+1,q0+id1+1,cmp);
        int qp=1;
        while(1){
            if(qp<=id1){
                int w=q0[qp];
                if(l[w]!=d[w]){++qp;continue;}
                if(q1.size()&&l[q1.front()]<l[w])cal(q1.front()),q1.pop();
                else cal(w),++qp;
            }else if(q1.size())cal(q1.front()),q1.pop();
            else break;
        }
        int flow=0;
        for(int i=1;i<=id1;++tk,++i)if(l[i]==d[i]&&dfs(i))++flow,++d[i];
        for(int i=1;i<=flow;++i)++ap,as[ap]=as[ap-1]+lt;
        return flow;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                if(s[i][j]!='.')continue;
                id[i][j][0]=s[i-1][j]=='.'?id[i-1][j][0]:++id1;
                id[i][j][1]=s[i][j-1]=='.'?id[i][j-1][1]:++id2;
            }
        }
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j)if(s[i][j]=='.'){
                ae(id[i][j][0],id1+id[i][j][1]);
            }
        }
        id2+=id1;
        while(cal());
        for(scanf("%d",&q);q;--q){
            int x;
            scanf("%d",&x);
            printf("%d
    ",as[x]);
        }
        return 0;
    }
  • 相关阅读:
    C C++ POSIX 的一些 IO 操作
    左式堆的合并
    IDEA Maven 项目默认编译项目为JDK 1.5
    spring学习总结(一)_Ioc基础(中)
    SpringBoot(十五)_springboot实现预览pdf
    PostgreSQL之性能优化(转)
    PostgreSQL之Sequence序列(转)
    PostgreSQL之连接数修改
    CAS登陆过程UML中文版
    node 和npm 版本更新
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7122883.html
Copyright © 2011-2022 走看看