zoukankan      html  css  js  c++  java
  • 【AtCoder】ARC095 E

    【题目】E - Symmetric Grid

    【题意】给定n*m的小写字母矩阵,求是否能通过若干行互换和列互换使得矩阵中心对称。n,m<=12。

    【算法】模拟

    【题解】首先行列操作独立,如果已确定行操作,那么两个在对称位置的列要满足条件必须其中一列反转后和另一列相同,或m为奇数且此列在中间。

    已确定了行操作后,枚举每一列,找到它可以匹配的列直接匹配,后面如果矛盾了就直接无解(因为匹配的列都是确定的,不存在决策问题),复杂度O(nm^2)。

    如何确定行操作?枚举每一行的匹配行,虽然这样理论上会枚举n^(n/2)种情况,但其中只有(n-1)!!种情况合法并进入下一过程,故复杂度为O((n-1)!!*nm^2),极限为17962560,实际上列枚举存在大量返回会更快,甚至直接枚举列匹配都能2ms AC。

    代码来自:zhan8855

    #include <cstdio>
     
    char c[15][15],d[15],e[15];
    int i,m,n;
     
    inline bool dfs2(int x)
    {
        if (x>m)
            return true;
        if (e[x])
            return dfs2(x+1);
        else
        {
            int t=0,r=0;
            for (int i=x;i<=m;i++)
                if (! e[i])
                    t++;
            for (int i=x;i<=m;i++)
                if (! e[i])
                {
                    e[x]=i,e[i]=x,r=1;
                    for (int j=1;j<=n;j++)
                        if ((c[j][x]!=c[d[j]][i]) || (c[d[j]][x]!=c[j][i]))
                        {
                            r=0;
                            break;
                        }
                    if(i==x){
                        if(r&&(t&1)&&dfs2(x+1))return true;
                    }
                    else{
                        if(r){
                            if(dfs2(x+1))return true;else return false;
                        }
                    }
                    /*if ((r) && ((t&1) || (i!=x)) && (dfs2(x+1)))
                        return true;
                    else if(i!=x)return false;*/
                    e[x]=0,e[i]=0;
                }
        }
        return false;
    }
     
    inline bool dfs1(int x)
    {
        if (x>n)
            return dfs2(1);
        if (d[x])
            return dfs1(x+1);
        else
        {
            int t=0;
            for (int i=x;i<=n;i++)
                if (! d[i])
                    t++;
            for (int i=x;i<=n;i++)
                if (! d[i])
                {
                    d[x]=i,d[i]=x;
                    if (((t&1) || (i!=x)) && (dfs1(x+1)))
                        return true;
                    d[x]=0,d[i]=0;
                }
        }
        return false;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++)
            scanf("%s",c[i]+1);
        if (dfs1(1))
            puts("YES");
        else
            puts("NO");
        return 0;
    }
    View Code
  • 相关阅读:
    第四章 证券投资基金的监管
    第三章 证券投资基金类型
    第二章 证券投资基金概述
    第一章 金融、资产管理与投资基金
    第一章附录
    第1章 为什么研究货币、银行与金融市场
    最近值得珍惜的小事
    转_如何解决linux动态库版本控制
    爆裂鼓手
    修改jupyter notebook默认路径
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8849156.html
Copyright © 2011-2022 走看看