zoukankan      html  css  js  c++  java
  • BZOJ2150: 部落战争

    【传送门:BZOJ2150


    简要题意:

      给出一个矩阵,矩阵上的字符有两种,一种是'x',表示山洞(不可走),一种是'.',表示城镇

      可以在城镇处放士兵,士兵经过的每个城镇都会被占领,士兵只能向下走,而且行走的方式和马相似,不过马走的是1*2,士兵走的是R*C,士兵不能经过一个被占领的城镇

      求出最少派出多少个士兵能够占领所有城镇


    题解:

      最小路径覆盖问题,用二分图匹配

      将所有城镇拆成两个集合

      如果x能走到y,则x连向y的第二个集合的点

      然后将总点数-最大匹配数就是最小路径覆盖数了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    using namespace std;
    char st[51][51];
    struct node
    {
        int x,y,next;
    }a[21000];int len,last[6100];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    int dx[5],dy[5];
    int n,m,r,c;
    int p(int x,int y){return (x-1)*m+y;}
    int match[6100],chw[6100];
    bool findmuniu(int x,int t)
    {
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(chw[y]!=t)
            {
                chw[y]=t;
                if(match[y]==0||findmuniu(match[y],t)==true)
                {
                    match[y]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&r,&c);
        for(int i=1;i<=n;i++) scanf("%s",st[i]+1);
        len=0;memset(last,0,sizeof(last));
        dx[1]=r;dy[1]=-c;dx[2]=r;dy[2]=c;
        dx[3]=c;dy[3]=-r;dx[4]=c;dy[4]=r;
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(st[i][j]=='.')
                {
                    sum++;
                    for(int k=1;k<=4;k++)
                    {
                        int tx=i+dx[k],ty=j+dy[k];
                        if(tx<1||ty<1||tx>n||ty>m||st[tx][ty]=='x') continue;
                        ins(p(i,j),p(tx,ty)+n*m);
                    }
                }
            }
        }
        memset(chw,0,sizeof(chw));
        memset(match,0,sizeof(match));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(st[i][j]=='.')
                {
                    int t=p(i,j);
                    if(findmuniu(t,t)==true) sum--;
                }
            }
        }
        printf("%d
    ",sum);
        return 0;
    }

     

  • 相关阅读:
    TCP连接之报文首部
    Django基础篇--用户权限管理和组管理
    MySQL聚簇索引
    浅谈Redis之慢查询日志
    Django基础篇--模板和路由分发
    Django--数据库查询操作
    Django基础篇--Models
    Sqlautocode使用过程的一些坑
    关于域名的一点事
    unicode编码和utf8编码的区别
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8630246.html
Copyright © 2011-2022 走看看