Problem:
Problem F: The Castle

待ち伏せていた敵を見事撃破したうさぎは, 主人公を敵の城内に進めることに成功した. 主人公が城の地下牢に捕らわれていたねこたちを解放したところ, 彼らのうちの何匹かが主人公の力になってくれることになった.

ねこたちの話では, 城の奥にいる魔王に辿りつくには1 番からn 番のn 個の部屋をこの順に通り抜けることになるが, 各部屋には1 体ずつ敵が待ち受けていて逐一倒していかなければならないという. 仲間になったm匹のねこそれぞれについて, 各部屋の敵それぞれに対する勝率が分かっており, 主人公はこのねこたちを1 匹ずつ城の奥へ向けて派遣する. 各部屋はそこにいる敵を倒してからでなければ通過できないので, あるねこがある部屋の敵にやられたら, 次のねこはその部屋の敵から戦っていくことになる.

派遣されたねこは敵にやられるまで進むが, 派遣したねこがどの部屋の敵にやられたかは毎回知ることができ, それによって次にどのねこを派遣するかを決めることができる. どのようにすれば, ねこたちが待ち受けるすべての敵を倒せる確率が最大になるだろうか.

Input

入力の一行目にはm とn がスペースで区切られて与えられる. 1 ≤ m, n ≤ 16

つづくm 行には, 猫が敵に勝つ確率を表すn 個の実数が与えられる. i + 1 行目のj 個目の実数は, j 番の部屋の敵に勝つ確率を表している. 確率は小数点以下3 桁まで.

Output

ねこたちが待ち受けるすべての敵を倒せる確率が最大になるようにうまく順番を決めていくとき, その確率を答えよ. 出力は誤差を含んでいてもよいが, 真の値との誤差は10−9 以内にせよ.

Sample Input 1

2 3
0.900 0.500 0.100
0.500 0.500 0.500

Sample Output 1

0.372500000000

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.Arrays;
import java.util.Scanner;

//The Castle
public class Main{

	int m, n;
	double[][] dp, p;

	double get(int S, int K){
//		System.out.println("S:"+S+" K:"+K);
		if(dp[S][K]!=-1)return dp[S][K];
		double res = 0;
		for(int last=0;last<m;last++)if(((S>>last)&1)>0){
			double sum = 0;
			for(int j=0;j<=K;j++){
				double e = get(S-(1<<last), j);
				for(int k=j+1;k<=K;k++)e*=p[last][k];
				e*=1-p[last][K+1];
				sum += e;
			}
			res = Math.max(res, sum);
		}
		return dp[S][K] = res;
	}

	void run(){
		Scanner sc = new Scanner(System.in);
		m = sc.nextInt(); n = sc.nextInt();
		p = new double[m][n+2];
		for(int i=0;i<m;i++){
			p[i][0] = 1;
			for(int j=1;j<=n;j++)p[i][j]=sc.nextDouble();
		}
		dp = new double[1<<n][n+1];
		for(double[]d:dp)Arrays.fill(d, -1);
		for(int i=0;i<m;i++)for(int j=0;j<=n;j++){
			double e = 1;
			for(int k=0;k<=j;k++)e*=p[i][k];
			e*=1-p[i][j+1];
			dp[1<<i][j] = e;
		}
		double res = 0;
		for(int S=1;S<1<<m;S++)res=Math.max(res, get(S, n));
		System.out.printf("%.10f\n", res);
//		System.out.printf("%.10f\n", get(1, 0));
//		System.out.printf("%.10f\n", get(1, 1));
//		System.out.printf("%.10f\n", get(1, 2));
//		System.out.printf("%.10f\n", get(1, 3));
//		System.out.printf("%.10f\n", get(2, n));
	}

	public static void main(String[] args) {
		new Main().run();
	}
}