codeparrot/codecomplex huggingface dataset:
// Problem: 1102_F. Elongated Matrix
// Time complexity: np
import java.util.*;
import java.io.*;

public class main{

	static int max = 5000+1;
	static FastReader in = new FastReader();
	static PrintWriter out = new PrintWriter(System.out);
	static int N = 18;
	static int[][] mn1 = new int[N][N]; 
	static int[][] mn2 = new int[N][N];
	static int[][] dp = new int[1<<N][N];
	static int n,m;
	
	static void solve(){
		n = in.nextInt(); m = in.nextInt();
		int[][] a = new int[n][m];
		for(int i=0;i<n;i++)for(int j=0;j<m;j++)a[i][j] = in.nextInt();
		for(int i=0;i<n;i++){
			Arrays.fill(mn1[i],Integer.MAX_VALUE);
			Arrays.fill(mn2[i],Integer.MAX_VALUE);
		}
		
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				for(int k=0;k<m;k++){
					mn1[i][j] = Math.min(mn1[i][j],Math.abs(a[i][k]-a[j][k]));
					if(k<=m-2)
						mn2[i][j] = Math.min(mn2[i][j],Math.abs(a[i][k]-a[j][k+1]));
				}
		int ans = 0;
		for(int i=0;i<n;i++){
			for(int x=0;x<1<<n;x++)Arrays.fill(dp[x],-1);
			for(int j=0;j<n;j++)dp[1<<j][j] = 0;
			dp[1<<i][i] = Integer.MAX_VALUE;
			for(int j=0;j<n;j++)
				ans = Math.max(ans,Math.min(mn2[j][i],calc((1 << n) - 1, j)));
		}
		out.println(ans);
	}

	static int calc(int mask, int v){
		if (dp[mask][v] != -1)
			return dp[mask][v];
		dp[mask][v] = 0;
		for(int u=0;u<n;u++) if (v != u && (((mask >> u) & 1)>0))
			dp[mask][v] = Math.max(dp[mask][v], Math.min(mn1[u][v], calc(mask ^ (1 << v), u)));
		return dp[mask][v];
	}


	public static void main(String[] args){
		solve();
		out.flush();
		out.close();
	}	

	static class FastReader{
        BufferedReader br;
        StringTokenizer st;
        public FastReader(){
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public FastReader(String s) throws Exception{
            br = new BufferedReader(new FileReader(s));
        }

        String next(){
            while (st == null || !st.hasMoreElements()){
                try{
                    st = new StringTokenizer(br.readLine());
                }catch (IOException  e){
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        String nextLine(){
            String str = "";
            try{   
                str = br.readLine();
            }catch (IOException e){
                e.printStackTrace();
            }  
            return str;
        }
        int nextInt(){return Integer.parseInt(in.next());}
    	long nextLong(){return Long.parseLong(in.next());}
    	double nextDouble(){return Double.parseDouble(in.next());}
    }
}




// |xvcxv|vcv[cvcvc|cxv||]vcvx:v|c|vxc|[|cvx:cxvx||||]
// Problem: 1102_F. Elongated Matrix
// Time complexity: np

import java.io.*;
import java.util.*;

public class D{

	static int bot;
	static int n,m;
	static int [][]a;
	static int [][]Min;
	static int [][]memo;
	static int K;
	static int dp(int msk,int ones,int last) {
		if(ones==n) {
			return Min[last][bot]>=K?1:0;
		}
		if(memo[last][msk]!=-1)
			return memo[last][msk];
		int ans=0;
		for(int nxt=0;nxt<n;nxt++)
			if((msk & (1<<nxt)) ==0 && Min[last][nxt]>=K)
			{
				ans|=dp(msk|1<<nxt,ones+1,nxt);
			}
		return memo[last][msk]= ans;
	}
	static boolean check(int top,int bottom) {
		for(int j=0;j+1<m;j++)
		{
			int diff=Math.abs(a[bottom][j]-a[top][j+1]);
			if(diff<K)
				return false;
		}
		return true;
	}
	public static void main(String[] args) throws IOException {
		Scanner sc=new Scanner();
		PrintWriter out=new PrintWriter(System.out);
		n=sc.nextInt();
		m=sc.nextInt();
		a=new int [n][m];
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				a[i][j]=sc.nextInt();
		Min=new int [n][n];
		if(n==1) {
			int lo=0,hi=(int)1e9;
			int ans=0;
			while(lo<=hi) {
				K=lo+hi>>1;
				
				if(check(0, 0))
				{
					ans=K;
					lo=K+1;
				}
				else
					hi=K-1;
			}
			System.out.println(ans);
			return;
		}
		for(int i1=0;i1<n;i1++)
			for(int i2=0;i2<n;i2++)
			{
				if(i1==i2)
					continue;
				int min=(int) 1e9;
				for(int j=0;j<m;j++)
					min=Math.min(Math.abs(a[i1][j]-a[i2][j]), min);
				Min[i1][i2]=min;
			}
		memo=new int [n][1<<n];
		int ans=0;
		int lo=0,hi=(int)1e9;
		while(lo<=hi) {
			K=lo+hi>>1;
		for(int []x:memo)
			Arrays.fill(x, -1);
		int ok=0;
		for(int top=0;top<n && ok==0;top++)
			for(int bottom=0;bottom<n && ok==0 ;bottom++) {
				bot=bottom;
				if(top==bottom || !check(top, bottom))
					continue;
				
				
				int dp=dp(1<<top | 1<<bottom, 2, top);
				ok|=dp;
				
			}
		if(ok==1)
		{
			ans=K;
			lo=K+1;
			
		}
		else
			hi=K-1;
		}
		out.println(ans);
		
		out.close();

	}
	static class Scanner
	{
		BufferedReader br;
		StringTokenizer st;
		Scanner(){
			br=new BufferedReader(new InputStreamReader(System.in));
		}
		Scanner(String fileName) throws FileNotFoundException{
			br=new BufferedReader(new FileReader(fileName));
		}
		String next() throws IOException {
			while(st==null || !st.hasMoreTokens())
				st=new StringTokenizer(br.readLine());
			return st.nextToken();
		}
		String nextLine() throws IOException {
			return br.readLine();
		}
		int nextInt() throws IOException{
			return Integer.parseInt(next());
		}
		long nextLong()  throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}
		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}
	}
}
// Problem: 1102_F. Elongated Matrix
// Time complexity: np
import java.util.Scanner;

public class Main {
	
	private static boolean check(int n , int m , int k) {
		
		for (int i = 0;i < n;i ++) {
			for (int j = 0;j < n;j ++) {
				for (int l = 0;l < (1 << n);l ++) {
					dp[i][j][l] = - 1;
				}
			}
		}
		for (int i = 0;i < n;i ++) {
			if (dfs(i , i , n , m , k , 0)) {
				return true;
			}
		}
		return false;
		
	}	
	
	private static boolean dfs(int first , int current , int n , int m , int k , int bitmap) {
	
		bitmap |= (1 << current);
		if (bitmap == (1 << n) - 1) {
			// check first and current			
			if (n == 1) {
				if (m > 1) {
					if (rowMinDist[current] >= k) {
						return true;
					} else {					
						return false;
					}
				} else {
					return true;
				}
			} else {
				if (m > 1) {
					if (minDistBetweenHeadAndTail[first][current] >= k) {
						return true;
					} else {
						return false;
					}
				} else {
					return true;
				}
			}
		} else {
			if (dp[first][current][bitmap] >= 0) {
				if (dp[first][current][bitmap] > 0) {
					return true;
				} else {
					return false;
				}
			}
			
			short ans = 0;
			for (int i = 0;i < n;i ++) {
				if ((bitmap & (1 << i)) == 0 && minDistBetweenRow[current][i] >= k) {					
					if (dfs(first , i , n , m , k , bitmap)) {
						ans = 1;
						break;
					}
				}
			}
			
			dp[first][current][bitmap] = ans;
			if (ans > 0) {			
				return true;
			} else {
				return false;
			}
		}
		
	}

	private static short[][][] dp = new short[20][20][(1 << 17)];	
	private static int[][] input = new int[20][10010];
	private static int[][] minDistBetweenRow = new int[20][20];
	private static int[][] minDistBetweenHeadAndTail = new int[20][20];
	private static int[] rowMinDist = new int[20];
	
	public static void main(String[] args) {		
	
		Scanner scan = new Scanner(System.in);
	
		int i , j , k , n , m;
		n = scan.nextInt();
		m = scan.nextInt();
		for (i = 0;i < n;i ++) {
			for (j = 0;j < m;j ++) {
				input[i][j] = scan.nextInt();
			}
		}
		for (i = 0;i < n;i ++) {
			for (j = i + 1;j < n;j ++) {
				int minDist = - 1;
				for (k = 0;k < m;k ++) {
					int dist = Math.abs(input[i][k] - input[j][k]);
					if (dist < minDist || minDist < 0) {
						minDist = dist;
					}
				}
				minDistBetweenRow[i][j] = minDistBetweenRow[j][i] = minDist;		
			}
		}
		for (i = 0;i < n;i ++) {
			for (j = 0;j < n;j ++) {
				if (i != j) {
					// i head , j tail
					int minDist = - 1;
					for (k = 0;k < m - 1;k ++) {						
						int dist = Math.abs(input[j][k] - input[i][k + 1]);
						if (dist < minDist || minDist < 0) {
							minDist = dist;
						}
					}
					minDistBetweenHeadAndTail[i][j] = minDist;
				}
			}
		}		
		for (i = 0;i < n;i ++) {
			int minDist = - 1;
			for (j = 0;j < m - 1;j ++) {
				int dist = Math.abs(input[i][j] - input[i][j + 1]);
				if (dist < minDist || minDist < 0) {
					minDist = dist;
				}
			}
			rowMinDist[i] = minDist;
		}
		int low = 0 , high = 1000000010;
		while (low < high) {
			int mid = (low + high) / 2;
			if (check(n , m , mid)) {				
				low = mid + 1;
			} else {
				high = mid;
			}
		}
		System.out.println(high - 1);

	}
   
    
}
// Problem: 1102_F. Elongated Matrix
// Time complexity: np
/*
If you want to aim high, aim high
Don't let that studying and grades consume you
Just live life young
******************************
What do you think? What do you think?
1st on Billboard, what do you think of it
Next is a Grammy, what do you think of it
However you think, I’m sorry, but shit, I have no fcking interest
*******************************
I'm standing on top of my Monopoly board
That means I'm on top of my game and it don't stop
til my hip don't hop anymore
https://www.a2oj.com/Ladder16.html
*******************************
300IQ as writer = Sad!
*/
import java.util.*;
import java.io.*;
import java.math.*;

   public class F
   {
      public static void main(String hi[]) throws Exception
      {
         BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));  
         StringTokenizer st = new StringTokenizer(infile.readLine());
         int N = Integer.parseInt(st.nextToken());
         int M = Integer.parseInt(st.nextToken());
         int[][] grid = new int[N][M];
         for(int i=0; i < N; i++)
            grid[i] = readArr(M, infile, st);
         int[][] mindiff = new int[N][N];
         for(int a=0; a < N; a++)
            for(int b=a+1; b < N; b++)
            {
               int val = Integer.MAX_VALUE;
               for(int i=0; i < M; i++)
                  val = Math.min(val, Math.abs(grid[a][i]-grid[b][i]));
               mindiff[a][b] = mindiff[b][a] = val;
            }
         int res = 0;
         for(int start=0; start < N; start++)
         {
            int[][] dp = new int[1<<N][N];
            Arrays.fill(dp[0], Integer.MAX_VALUE);
            for(int mask=0; mask < (1<<N); mask++)
            {
               if(Integer.bitCount(mask) == 1 && mask != (1<<start))
                  continue;
               for(int prev=0; prev < N; prev++)
                  if((mask&(1<<prev)) > 0 || mask == 0)
                  {
                     for(int b=0; b < N; b++)
                        if((mask&(1<<b)) == 0)
                        {
                           int submask = mask|(1<<b);
                           if(mask == 0)
                              dp[submask][b] = Integer.MAX_VALUE;
                           else
                              dp[submask][b] = Math.max(dp[submask][b], Math.min(dp[mask][prev], mindiff[prev][b]));
                        }
                  }
            }
            for(int b=0; b < N; b++)
            {
               int temp = dp[(1<<N)-1][b];
               for(int i=0; i < M-1; i++)
                  temp = Math.min(temp, Math.abs(grid[b][i]-grid[start][i+1]));
               res = Math.max(res, temp);
            }
         }
         System.out.println(res);
      }
      public static int[] readArr(int N, BufferedReader infile, StringTokenizer st) throws Exception
      {
         int[] arr = new int[N];
         st = new StringTokenizer(infile.readLine());
         for(int i=0; i < N; i++)
            arr[i] = Integer.parseInt(st.nextToken());
         return arr;
      }
   }
// Problem: 112_E. Petya and Spiders
// Time complexity: np
import java.io.*;
import java.util.*;

public class E
{
	private static final int oo = 1000000000;
	public static void main(String[] args) throws Exception
	{
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		if(n > m)
		{
			int t = n;
			n = m;
			m = t;
		}

		int [][] curr = new int[1<<n][1<<n];
		fill(curr, oo);
		Arrays.fill(curr[0], 0);

		for(int j = 0 ; j < m ; j++)
		{
			int [][] next = new int[1<<n][1<<n];
			fill(next, oo);
			for(int c0 = 0 ; c0 < 1<<n ; c0++)
				for(int c1 = 0 ; c1 < 1<<n ; c1++)
					if(curr[c0][c1] != oo)
						for(int c2 = 0 ; c2 < (j == m-1 ? 1 : 1<<n) ; c2++)
						{
							int done = 0;
							for(int i = 0 ; i < n ; i++)
								if(((1<<i) & c1) == 0)
								{
									int up = i-1;
									int down = i+1;
									if(up >= 0 && ((1<<up) & c1) != 0)
										done |= 1<<i;
									if(down < n && ((1<<down) & c1) != 0)
										done |= 1<<i;
									if(((1<<i) & c0) != 0)
										done |= 1<<i;
									if(((1<<i) & c2) != 0)
										done |= 1<<i;
								}

							next[c1][c2] = Math.min(next[c1][c2], curr[c0][c1] + n - Integer.bitCount(done));

						}
			curr = next;
		}

		int res = oo;
		for(int i = 0 ; i < 1<<n ; i++)
			for(int j = 0 ; j < 1<<n ; j++)
				res = Math.min(res, curr[i][j]);

		System.out.println(n*m - res);
	}

	private static void fill(int[][] array, int val)
	{
		for(int [] fill : array)
			Arrays.fill(fill, val);
	}
}
// Problem: 112_E. Petya and Spiders
// Time complexity: np
import java.util.*;

public class cf112e {
	static int n,m,s;
	static int[][][] memo;
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		m = in.nextInt();
		if(n > m) {
			int tmp = n;
			n = m;
			m = tmp;
		}
		s = (1<<n);
		memo = new int[s][s][m];
		for(int i=0; i<s; i++)
			for(int j=0; j<s; j++)
				Arrays.fill(memo[i][j], -1);
		int ret = go(0,0,0);
		System.out.println(n*m - ret);
	}
	static int go(int last, int trans, int r) {
		if(r==m) {
			if(trans == 0) return 0;
			return 100;
		}
		if(memo[last][trans][r] != -1) return memo[last][trans][r];
		int best = 100;
		for(int crnt = 0; crnt < s; crnt++) {
			if((trans & ~crnt) != 0) continue; //certain ones have to be here
			for(int pass = 0; pass < s; pass++) {
				int tmp = ((1<<n)-1) & ~last;	//move back the ones you can
				if((pass & ~tmp) != 0) continue; //certain ones have to move on
				tmp = tmp & ~pass; //find which ones stay
				boolean fail = false;
				for(int k=0; k<n; k++) //make sure that the ones that stay
					if(isSet(tmp,k) && !(isSet(crnt,k-1) || isSet(crnt,k) || isSet(crnt,k+1)))
						fail = true;
				if(fail) continue;
				best = Math.min(best, Integer.bitCount(crnt) + go(crnt,pass,r+1));
			}
		}
		return memo[last][trans][r] = best;
	}
	static boolean isSet(int x, int p) {
		if(p < 0 || p >= n) return false;
		return (x & (1<<p)) != 0;
	}
}
// Problem: 112_E. Petya and Spiders
// Time complexity: np
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

/**
 * Author -
 * User: kansal
 * Date: 9/3/11
 * Time: 5:28 PM
 */
public class CF85C {
    public static void main(String[] args) {
        reader = new BufferedReader(new InputStreamReader(System.in));

        int height = nextInt(), width = nextInt();
        if (width > height) {
            int t = width;
            width = height;
            height = t;
        }

        final int INF = height * width + 10;
        final int ALL_BITS = (1 << width)  - 1;
        int[][][] dp = new int[height + 1][1 << width][1 << width];
        for (int[][] ints : dp) {
            for (int[] anInt : ints) {
                Arrays.fill(anInt, INF);
            }
        }

        dp[0][0][0] = 0;
        for(int r = 0; r < height; ++r) {
            for(int uncovered = 0; uncovered < (1 << width); ++uncovered) {
                for(int mask = 0; mask < (1 << width); ++mask) {
                    if (dp[r][uncovered][mask] == INF) {
                        continue;
                    }
                    for(int curMask = uncovered; curMask < (1 << width); curMask = (curMask + 1) | uncovered) {
                        int curCovered = (mask | curMask);
                        curCovered |= (curMask >> 1);
                        curCovered |= (ALL_BITS & (curMask << 1));

                        int curUncovered = ALL_BITS ^ curCovered;
                        dp[r+1][curUncovered][curMask] = Math.min(dp[r+1][curUncovered][curMask], dp[r][uncovered][mask] + Integer.bitCount(curMask));
                    }
                }
            }
        }

        int res = INF;
        for(int x: dp[height][0]) res = Math.min(res, x);

        System.out.println(height * width - res);
    }

    private static boolean hasBit(int mask, int bit) {
        return (((mask >> bit) & 1) == 1);
    }

    public static BufferedReader reader;

    public static StringTokenizer tokenizer = null;

    static String nextToken() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    static public int nextInt() {
        return Integer.parseInt(nextToken());
    }

    static public long nextLong() {
        return Long.parseLong(nextToken());
    }

    static public String next() {
        return nextToken();
    }

    static public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}
// Problem: 112_E. Petya and Spiders
// Time complexity: np
/*
If you want to aim high, aim high
Don't let that studying and grades consume you
Just live life young
******************************
If I'm the sun, you're the moon
Because when I go up, you go down
*******************************
I'm working for the day I will surpass you
https://www.a2oj.com/Ladder16.html
*/
import java.util.*;
import java.io.*;
import java.math.*;

   public class x111C
   {
      public static void main(String omkar[]) throws Exception
      {
         BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));  
         StringTokenizer st = new StringTokenizer(infile.readLine());
         int R = Integer.parseInt(st.nextToken());
         int C = Integer.parseInt(st.nextToken());
         if(R > C)
         {
            int t = R;
            R = C;
            C = t;
         }
         //dp[c][m1][m2] = min spoders in first c columns
         int[][][] dp = new int[C+1][1 << R][1 << R];
         for(int i=0; i <= C; i++)
            for(int mask=0; mask < (1<<R); mask++)
               Arrays.fill(dp[i][mask], 69);
         for(int mask=0; mask < (1<<R); mask++)
            dp[0][0][mask] = 0;
         for(int c=1; c <= C; c++)
            for(int mask1=0; mask1 < (1<<R); mask1++)
               for(int mask2=0; mask2 < (1<<R); mask2++)
                  for(int mask3=0; mask3 < (1<<R); mask3++)
                  {
                     boolean works = true;
                     for(int b=0; b < R; b++)
                        if((mask2&(1<<b)) == 0)
                        {
                           if(b > 0 && (mask2&(1<<(b-1))) > 0);
                           else if(b+1 < R && (mask2&(1<<(b+1))) > 0);
                           else if((mask1&(1<<b)) > 0);
                           else if((mask3&(1<<b)) > 0);
                           else  works = false;
                        }
                     if(works)
                        dp[c][mask2][mask3] = Math.min(dp[c][mask2][mask3], dp[c-1][mask1][mask2]+Integer.bitCount(mask1));
                  }
         int res = 0;
         for(int mask=0; mask < (1<<R); mask++)
            res = Math.max(res, R*C-(dp[C][mask][0]+Integer.bitCount(mask)));
         System.out.println(res);
      }
   }
// Problem: 112_E. Petya and Spiders
// Time complexity: np

import java.util.*;


public class E
{
   public static void main(String[] args)
   {
      new E(new Scanner(System.in));
   }

   int N, M;
   int[][][] memo;

   int go(int i, int j, int mask)
   {
      if (i == N)
         return go(0, j+1, mask);
      if (j == M)
      {
         int mm = mask%(1<<N);
         //System.out.println(Integer.toBinaryString(mm)+" "+Integer.toBinaryString(mask));
         if (mm != ((1<<N)-1))
            return N*M;
         return 0;
      }

      if (memo[i][j][mask] != -1)
         return memo[i][j][mask];

      // Now place a spider cluster here
      int nMask = mask;
      int prevMask = 0;
      if (i > 0)
         prevMask = 1 << (N-1);
      int nextMask = 0;
      if (i < (N-1))
         nextMask = 1 << (N+1);
      int curMask = 1 << N;
      int nextRowMask = 1 << (N+N);
      nMask = nMask|prevMask|nextMask|curMask|nextRowMask;
      nMask = nMask/2;
      int res = 1+go(i+1, j, nMask);
      
      int pr = mask%2;
      if (pr == 1)
      {
         // We have the option to skip here
         int rr = go(i+1, j, mask/2);
         if (rr < res)
            res = rr;
      }

   
      //System.out.printf("%d %d %s = %d%n", i, j, Integer.toBinaryString(mask), res);
      memo[i][j][mask] = res;
      return res;
   }

   public E(Scanner in)
   {
      int[] vals = new int[2];
      vals[0] = in.nextInt();
      vals[1] = in.nextInt();
      Arrays.sort(vals);

      N = vals[0];
      M = vals[1];
      memo = new int[N][M][1<<(N+N+1)];
      fill3(memo, -1);
      
      int r1 = go(0, 0, (1<<N)-1);
      int res = N*M-r1;
      System.out.printf("%d%n", res);
   
   }

   void fill3(int[][][] vvv, int val)
   {
      for (int[][] vv : vvv)
         for (int[] v : vv)
            Arrays.fill(v, val);
   }
}
// Problem: 112_E. Petya and Spiders
// Time complexity: np
import java.io.*;
import java.util.*;

public class E
{
    private static final int oo = 1000000000;
    public static void main(String[] args) throws Exception
    {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        if(n > m)
        {
            int t = n;
            n = m;
            m = t;
        }

        int [][] curr = new int[1<<n][1<<n];
        fill(curr, oo);
        Arrays.fill(curr[0], 0);

        for(int j = 0 ; j < m ; j++)
        {
            int [][] next = new int[1<<n][1<<n];
            fill(next, oo);
            for(int c0 = 0 ; c0 < 1<<n ; c0++)
                for(int c1 = 0 ; c1 < 1<<n ; c1++)
                    if(curr[c0][c1] != oo)
                        for(int c2 = 0 ; c2 < (j == m-1 ? 1 : 1<<n) ; c2++)
                        {
                            int all = (1<<n) - 1;
                            int done = (all&(c1>>1)) | (all&(c1<<1)) | c0 | c2;
                            done &= (all^c1);

                            next[c1][c2] = Math.min(next[c1][c2], curr[c0][c1] + n - Integer.bitCount(done));

                        }
            curr = next;
        }

        int res = oo;
        for(int i = 0 ; i < 1<<n ; i++)
            for(int j = 0 ; j < 1<<n ; j++)
                res = Math.min(res, curr[i][j]);

        System.out.println(n*m - res);
    }

    private static void fill(int[][] array, int val)
    {
        for(int [] fill : array)
            Arrays.fill(fill, val);
    }
}