import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, M, max;
static char[][] map;
static boolean[][] used;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
max = Integer.MIN_VALUE;
map = new char[N][M];
used = new boolean[N][M];
for (int i = 0; i < N; i++) {
String s = br.readLine();
for (int j = 0; j < M; j++) {
map[i][j] = s.charAt(j);
}
}
dfs(0,0);
System.out.println(max);
}
private static void dfs(int row, int col) {
// 선택 완료 -> 최댓값 갱신
if (row == N) {
updateMax();
return;
}
// 다음행으로 이동
if (col == M) {
dfs(row+1, 0);
return;
}
// 가로, 세로 선택 가지 뻗기
used[row][col] = true;
dfs(row, col+1);
used[row][col] = false;
dfs(row, col+1);
}
private static void updateMax() {
int sum = getSum();
max = Math.max(max, sum);
}
private static int getSum() {
int sum = 0;
// 가로 계산
sum = getRowSum(sum);
// 세로 숫자 계산
sum = getColSum(sum);
return sum;
}
private static int getColSum(int sum) {
for (int i = 0; i < N; i++) {
int temp = 0;
for (int j = 0; j < M; j++) {
if (!used[i][j]) {
temp *= 10;
temp += map[i][j] - '0';
} else {
sum += temp;
temp = 0;
}
}
sum += temp;
}
return sum;
}
private static int getRowSum(int sum) {
for (int i = 0; i < M; i++) {
int temp = 0;
for (int j = 0; j < N; j++) {
if (used[j][i]) {
temp *= 10;
temp += map[j][i] - '0';
} else {
sum += temp;
temp = 0;
}
}
sum += temp;
}
return sum;
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, M, max;
static int[][] map;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
max = Integer.MIN_VALUE;
map = new int[N][M];
init(br);
bitmask();
print();
}
private static void init(BufferedReader br) throws IOException {
for (int i = 0; i < N; i++) {
String s = br.readLine();
for (int j = 0; j < M; j++) {
map[i][j] = s.charAt(j) - '0';
}
}
}
private static void bitmask() {
for(int s=0; s<(1<<(N*M)); s++) {
int sum = 0;
/* 가로(0) 찾기 */
sum = getRowSum(s, sum);
/* 세로(1) 찾기 */
sum = getColSum(s, sum);
/* 최댓값 갱신 */
updateMax(sum);
}
}
private static int getColSum(int s, int sum) {
for(int j=0; j<M; j++) {
int cur = 0;
for(int i=0; i<N; i++) {
int k = i*M +j;
if( (s &(1<<k)) != 0) { // s의 k번째 비트가 1이면-> 해당 숫자는 세로
cur *= 10;
cur += map[i][j];
}else { // 해당 숫자는 가로
sum += cur;
cur = 0;
}
}
sum += cur;
}
return sum;
}
private static int getRowSum(int s, int sum) {
for(int i=0; i<N; i++) {
int cur = 0;
for(int j=0; j<M; j++) {
int k = i*M+j;
if( (s &(1<<k)) ==0 ) { // s의 k번째 비트가 0이면-> 해당 숫자는 가로
cur*= 10;
cur += map[i][j];
}else { // 해당 숫자는 세로
sum += cur;
cur = 0;
}
}
sum += cur;
}
return sum;
}
private static void updateMax(int sum) {
max = Math.max(max, sum);
}
private static void print() {
System.out.println(max);
}
}
true
, 세로는 false
로 방문 배열을 체크함getSum
메소드), 최댓값을 갱신함(updateMax
메소드)getColSum, getRowSum
메소드