#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stack>
#include <functional>
#include <queue>
#include <tuple>
#include <cstring>
#include <iomanip>

using namespace std;

#define rep(i,n) for(int i = 0;i < n;i++)
#define each(i,n) for(auto i : n)
#define all(n) n.begin(),n.end()
#define clr(n) memset(n,0,sizeof(n))
#define mclr(n) memset(n,-1,sizeof(n))

//dp[bit][i][j] ?´???£??????????????????bit???i???????????¨?±????j?????????????????????
//??¨??¨????????????????¢????
double dp[1 << 16][16];

//ap[i][j][k] ???i ?????¨?±?j????????¨?±?k?????????????¢????
double ap[16][16][17];
double a[16][17];

int main() {
	int n, m;
	cin >> m >> n;
	mclr(dp);
	rep(i, m) {
		rep(j, n) {
			cin >> a[i][j];
		}
		a[i][n] = 0.0;
	}
	rep(i, m) {
		rep(j, n) {
			rep(k, n + 1) {
				ap[i][j][k] = 1.0;
				for (int l = j; l < k; l++) {
					ap[i][j][k] *= a[i][l];
				}
				ap[i][j][k] *= (1.0 - a[i][k]);
			}
		}
	}
	function<double(int, int)> solve = [&](int bit, int i) {
		if (i == n)return 1.0;
		if (dp[bit][i] >= -0.5) {
			return dp[bit][i];
		}
		double re = 0.0;
		rep(k, m) if(!(bit & (1 << k))) {
			double p = 0.0;
			for (int l = i; l <= n; l++) {
				p += solve(bit | (1 << k), l) * ap[k][i][l];
			}
			re = max(re, p);
		}
		return dp[bit][i] = re;
	};
	cout << fixed << setprecision(30) << solve(0, 0) << endl;
	
	return 0;
}