#include <bits/stdc++.h>
using namespace std;

int M, N;
double P[16][16];

int i, j, k, S;
double win, lose, ans;
double dp[17][1 << 16][16];

int main(void) {
  cin >> M >> N;
  for(i = 0; i < M; i++) for(j = 0; j < N; j++) cin >> P[i][j];

  /* 状態:
   *   dp[i][S][j] =
   *     集合Sのねこをすでに使っていて,
   *     敵iとねこjが戦うときに最善の行動をした場合の確率
   * 基底:
   *   dp[N][S][j] = 1
   *   where S in [0, 1 << N), j in [0, M)
   * 遷移:
   *   dp[i][S][j] = dp[i + 1][S][j] * P[j][i] + max(dp[i][S | (1 << k)][k]) * (1 - P[j][i])
   *   where k not in S
   */

  for(S = 0; S < (1 << M); S++) for(j = 0; j < M; j++) dp[N % 2][S][j] = 1;

  for(i = N - 1; i >= 0; i--) {
    for(S = 0; S < (1 << M); S++) for(j = 0; j < M; j++) dp[i % 2][S][j] = 0;
    for(S = (1 << M) - 1; S >= 0; S--) {
      for(j = 0; j < M; j++) if(S & (1 << j)) {
        win = dp[(i + 1) % 2][S][j] * P[j][i];
        lose = 0;
        for(k = 0; k < M; k++) if(!(S & (1 << k))) {
          lose = max(lose, dp[i % 2][S | (1 << k)][k] * (1 - P[j][i]));
        }
        dp[i % 2][S][j] = max(dp[i % 2][S][j], win + lose);
      }
    }
  }

  ans = 0;
  for(i = 0; i < M; i++) ans = max(ans, dp[0][1 << i][i]);
  printf("%.15lf\n", ans);
}
