1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Sample135 {
    public final int row;
    public final int col;

    private final boolean[][] initMatrix;
    private int rowCount = 0;

    public Sample135(int r, int c) {
        row = r;
        col = c;
        initMatrix = new boolean[r][];
    }
    public void setRow(int[] row) {
        initMatrix[rowCount] = new boolean[col];
        int index = 0;
        for (int cell: row) {
            initMatrix[rowCount][index++] = (cell == 0);
        }
        rowCount++;
    }
    public int calc() {
        int max = 0;
        // 行単位で、反転・そのままの全てのパターンを作成する
        List<boolean[][]> pattern = new ArrayList<boolean[][]>();
        pattern.add(initMatrix);
        for (int index = 0; index < row; index++) {
            List<boolean[][]> work = new ArrayList<boolean[][]>();
            for (boolean[][] matrix: pattern) {
                work.add(reverseRow(matrix, index));
            }
            pattern.addAll(work);
        }
        // 各パターンで、列単位でtrueが多い場合のpointを計算
        for (boolean[][] matrix: pattern) {
            int point = calcMaxPoint(matrix);
            if (max < point) max = point;
        }
        return max;
    }
    private boolean[][] reverseRow(boolean[][] matrix, int rIndex) {
        boolean[][] result = new boolean[row][];
        for (int index = 0; index < row; index++) {
            result[index] = copyRow(matrix[index], index == rIndex);
        }
        return result;
    }
    private boolean[] copyRow(boolean[] row, boolean reverse) {
        boolean[] result = new boolean[row.length];
        int index = 0;
        for (boolean b: row) {
            result[index++] = reverse? !b: b;
        }
        return result;
    }

    private int calcMaxPoint(boolean[][] matrix) {
        int sum = 0;
        for (int index = 0; index < col; index++) {
            int point = 0;
            for (boolean[] row: matrix) {
                if (row[index]) point++;
            }
            if (point <= row / 2) point = row - point;
            sum += point;
        }
        return sum;
    }


    private static int[] toIntArray(String[] input) {
        int[] result = new int[input.length];
        int index = 0;
        for (String s: input) {
            result[index++] = Integer.parseInt(s);
        }
        return result;
    }

    public static void main(String[] args) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        try {
            String[] table = reader.readLine().split("\\s");
            int r = Integer.parseInt(table[0]);
            int c = Integer.parseInt(table[1]);
            Sample135 sample = new Sample135(r, c);
            for (int index = 0; index < r; index++) {
                sample.setRow(toIntArray(reader.readLine().split("\\s")));
            }
            int result = sample.calc();
            System.out.println(result);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}