• Aizu


    Aizu - 0525

    子集枚举 DFS

    相似题目 飞行员兄弟 翻硬币 费解的开关

    这种类型的题目,有个典型的特征,翻偶数次等于没翻,只有翻奇数次才有效果

    即,要么翻,要么别翻,且操作之间是相互独立的,无序的

    这个题有两个操作,翻行,或者翻列,我们枚举操作少的哪一个,即枚举行操作用二进制来枚举

    然后对于每次的枚举结果,再进行列操作,而列并不需要真正的去翻,只需要统计那个多就行了

    因为只有两种状态,且状态之间是会相互转化的,所以直接统计,然后累计就是答案

    枚举每一种状态的时候记得要备份数组,因为你不能把原状态破坏了

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N = 1e4 + 10;
    int g[20][N],backup[20][N],ans,t,r,c;
    void turn_r(int x) {// 翻第 x 行所有的数
        for(int i = 0;i < c; ++i) {
            if(g[x][i] == 0) g[x][i] = 1;
            else g[x][i] = 0;
        }
    }
    int main() {
        while(scanf("%d%d",&r,&c) && r && c) {
            ans = 0;
            for(int i = 0;i < r; ++i)
                for(int j = 0;j < c; ++j)
                    scanf("%d",&g[i][j]);
            for(int i = 0;i < 1 << r; ++i) {
                t = 0;
                memcpy(backup,g,sizeof g);
                for(int j = 0;j < r; ++j) {
                    if(i >> j & 1) turn_r(j);// 翻这一行
                }
                for(int j = 0;j < c; ++j) {// 按列来统计
                    int w = 0,b = 0;
                    for(int k = 0;k < r; ++k) {
                        if(g[k][j] == 1) b ++;
                        else w ++;
                    }
                    t += max(w,b);
                }
                ans = max(t,ans);
                memcpy(g,backup,sizeof g);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    UML 类之间的关系
    [noi.ac省选模拟赛]第11场题解集合
    [CF1270F]Awesome Substrings
    [noi.ac省选模拟赛20200606]赌怪
    FFT,NTT入门
    [AHOI2017/HNOI2017]单旋
    [HNOI2016]最小公倍数
    [HNOI2016]树
    [HNOI2016]大数
    服务外包概论课程资料
  • 原文地址:https://www.cnblogs.com/lukelmouse/p/12450511.html
Copyright © 2020-2023  润新知