• [国家集训队]部落战争


    题目大意:给出n*m的矩阵以及r,c。求最小路径覆盖。

    本来是匈牙利算法裸题,网络流也可以跑一跑。

    但是我先粘一个骗分大错解:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,r,c,a[55],ans;
    char mp[55][55];
    int use[55][55],cov[55][55];
    int main()
    {
    //    freopen("legion.in","r",stdin);
    //    freopen("legion.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&r,&c);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",mp[i]+1);
            for(int j=1;j<=m;j++)
            {
                a[i]+=(mp[i][j]=='.');
                if(mp[i][j]=='x')use[i][j]=1;
            }
            ans+=a[i];
        }
        for(int i=1;i<=n;i++)
        {
            if(i>r)
            {
                for(int j=1;j<=m;j++)
                {
                    if(mp[i][j]=='x')continue;
                    if(j>c&&use[i-r][j-c]==0)
                    {
                        use[i-r][j-c]=1;
                        cov[i][j]=1;
                        ans--;
                    }else if(j+c<=m&&use[i-r][j+c]==0)
                    {
                        use[i-r][j+c]=1;
                        cov[i][j]=1;
                        ans--;
                    }
                }
            }
            if(r!=c&&i>c)
            {
                for(int j=1;j<=m;j++)
                {
                    if(cov[i][j])continue;
                    if(mp[i][j]=='x')continue;
                    if(j>r&&use[i-c][j-r]==0)
                    {
                        use[i-c][j-r]=1;
                        cov[i][j]=1;
                        ans--;
                    }else if(j+r<=m&&use[i-c][j+r]==0)
                    {
                        use[i-c][j+r]=1;
                        cov[i][j]=1;
                        ans--;
                    }
                }
            }
        }
        printf("%d
    ",ans);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    这是我考试时写的(因为没好好听匈牙利算法和网络流),但是无脑骗了60?

    放到某谷上面测70?

    恕我直言在座的数据都很强 

    接下来是正解:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 55
    int n,m,r,c,hed[N*N],cnt;
    char mp[N][N];
    struct EG
    {
        int to,nxt;
    }e[4*N*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int tn(int x,int y){return (x-1)*m+y;}
    int dx[4],dy[4],fa[N*N];
    bool vis[N*N];
    int dfs(int x)//Hungary
    {
        vis[x]=1;
        for(int j=hed[x];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(!vis[to])
            {
                vis[to]=1;
                if(!fa[to]||dfs(fa[to]))
                {
                    fa[to]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
    //    freopen("legion.in","r",stdin);
    //    freopen("legion.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&r,&c);
        dx[0]=dx[1]=dy[2]=r,dx[2]=dx[3]=dy[0]=c,dy[1]=-c,dy[3]=-r;
        for(int i=1;i<=n;i++)
            scanf("%s",mp[i]+1);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(mp[i][j]=='.')
                {
                    for(int k=0;k<4;k++)
                    {
                        int x = i+dx[k],y = j+dy[k];
                        if(x<=0||y<=0||x>n||y>m)continue;
                        if(mp[x][y]=='.')
                            ae(tn(i,j),tn(x,y));
                    }
                }
            }
        }
        int ans  =0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(mp[i][j]=='.')
                {
                    memset(vis,0,sizeof(vis));
                    ans+=(dfs(tn(i,j))==0);
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    在线编辑Office文件
    将自然数分解为若干连续的自然数
    C#远程连接Oracle数据库(不安装客户端)
    大数阶乘
    小写金额转换为大写金额
    SQL优化
    C#枚举器:foreach语句、IEnumerable、IEnumerator以及yield return (二)
    C#枚举器:foreach语句、IEnumerable、IEnumerator以及yield return (一)
    PPT播完最后一个动画后自动进入下一页
    C#中的abstract、virtual、override和new
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9743715.html
Copyright © 2020-2023  润新知