1 条题解

  • 0
    @ 2025-11-15 15:04:49

    行反转后 如果存在多个列全为1的情况 说明他们的原始模式要么相同要么互补

    主要利用位运算^以及利用掩码求反码; 以及利用位运算实现状态压缩 ;并且处理二维数组的方式解题

    不过我觉得这道题的核心难点在于能理解出上面黑体加粗的话的逻辑

    
    
    #引入collections库中的defaultdict库 
    # 目的是当字典中没有这个变量名的时候直接创立变量名以及对应的值
    from collections import defaultdict
    import sys
    
    def main():
        input = sys.stdin.read
        data = input().split()
        
        n, m = int(data[0]), int(data[1])
        #已经处理好矩阵
        rows = data[2:]
        
        #创建以列为标准的列表 用二进制存储行的0或1 使用状态压缩
        #空间压缩 把每列的01组合改成二进制 优化内存占用
        # 不优化达到9mb 压缩后仅需24kb
        col_patterns = [0] * m
        for i in range(n):#行
            for j in range(m):#列
                if rows[i][j] == '1':
                    #使用位运算 储存每个位的0或1的组合情况
                    col_patterns[j] |= (1 << i)
        #准备将每一列的组合存储计数
        pattern_count = defaultdict(int)
        #遍历每列的01组合模式
        for pattern in col_patterns:
            #defaultdict的作用 如果存储目标不在字典中 自动创建变量名
            pattern_count[pattern] += 1
        
        max_cols = 0
        #创建集合 避免重复 
        visited = set()
        #遍历已经存储好每个pattern数量的字典
        """利用for循环 就把这个题转换成了找到一个pattern标准 
          以这个pattern为基准反转后能获得的全1列最多的问题
                """
        for pattern in pattern_count:
            #如果这个模式已经存储过 跳过当前循环
            if pattern in visited:
                continue
            #利用二进制掩码和^运算 使取反
            """具体的运算过程:
                首先1左移n位 随后-1完成低n位变为1的操作
                随后进行^运算 实现反转操作
                例: 011 ^ 111 = 100"""
            flipped = ((1 << n) - 1) ^ pattern
            """ 查找反转后的列是否本身存在
             (get可以防止变量不存在于字典中返回相应的数字)"""
            
            """ 为什么要把"原模式"和"反模式"的列数加起来?  
                因为原模式与反模式经过特定次行反转后可以全部为1"""
            total = pattern_count[pattern] + pattern_count.get(flipped, 0)
            max_cols = max(max_cols, total)
            #由于存在反模式与模式同时存在的情况 于是将反模式与本模式全部加入集合
            #因为查询反模式与模式获得的total一样
            visited.add(pattern)
            visited.add(flipped)
        
        print(max_cols)
    
    if __name__ == "__main__":
        main()
    
      #无注释版:
      from collections import defaultdict
    import sys
    
    def main():
        input = sys.stdin.read
        data = input().split()
        
        n, m = int(data[0]), int(data[1])
        rows = data[2:]
        
        col_patterns = [0] * m
        for i in range(n):
            for j in range(m):
                if rows[i][j] == '1':
                    col_patterns[j] |= (1 << i)
        
        pattern_count = defaultdict(int)
        for pattern in col_patterns:
            pattern_count[pattern] += 1
        
        max_cols = 0
        visited = set()
        
        for pattern in pattern_count:
            if pattern in visited:
                continue
            flipped = ((1 << n) - 1) ^ pattern
            total = pattern_count[pattern] + pattern_count.get(flipped, 0)
            max_cols = max(max_cols, total)
            visited.add(pattern)
            visited.add(flipped)
        
        print(max_cols)
    
    if __name__ == "__main__":
        main()
      
    
    • 1

    [2025 实验室三面] 堵桥!堵桥!堵桥!

    信息

    ID
    1121
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    递交数
    30
    已通过
    9
    上传者