Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], skipTags: ["script","noscript","style","textarea","code"], processEscapes: true }});

問題文

$1,2,...,N$ を並べ替えた順列がある。2つの異なる数字 $i$, $j$ を選んで入れ替えることを繰り返してソートされた状態( $1,2,...,N$ の順番に並んだ状態)にしたい。
数字 $i$, $j$ を入れ替える度にコストが $c_{i,j}$ 必要になる。

順列 $p$ に対して、 $p$ をソートするのに必要な最小コストを $f(p)$ とする。
$f(p)$ のとりうる最大値を求めよ。

入力

入力は以下のフォーマットに従う。与えられる数は全て整数である。

$N$
$c_{1,1}$ $c_{1,2}$ $...$ $c_{1,N}$
$c_{2,1}$ $c_{2,2}$ $...$ $c_{2,N}$
$...$
$c_{N,1}$ $c_{N,2}$ $...$ $c_{N,N}$

制約

$2 \leq N \leq 8$

$0 \leq c_{i,j} \leq 10^5$

$c_{i,j} = c_{j,i}$

$c_{i,i} = 0$

出力

最大値を1行に出力せよ。

Sample Input 1

3
0 1 3
1 0 8
3 8 0

Output for the Sample Input 1

5

もっとも必要コストが大きい順列は$\{1,3,2\}$で、

1,2を入れ替えて$\{2,3,1\}$とする。

1,3を入れ替えて$\{2,1,3\}$とする。

1,2を入れ替えて$\{1,2,3\}$とする。

以上の操作によりコスト5でソートでき、またこれが最善であることが証明できる。
他の順列もコスト5以下でソートできることを示すことができる。

Solution in JAVA (judge verdict: Memory Limit Exceeded)

import java.util.*;

public class Main{

    int n;
    int[][] c;
    char[] per;
    boolean[] used;
    int goal,ans;
    ArrayList<String> slist;

    void solve(){
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt();
        c = new int[n][n];
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                int cc = sc.nextInt();
                c[i][j] = cc;
                c[j][i] = cc;
            }
        }

        String s = "";
        for(int i=1; i<=n; i++) s += Integer.toString(i);
        goal = Integer.parseInt(s);

        slist = new ArrayList<String>();
        per = new char[n];
        used = new boolean[n];
        ans = 0;
        dfs(0,0);

        System.out.println(ans);
    }

    void dfs(int pos,int num){
        if(pos==n){
            ans = Math.max(ans, dijkstra(new String(per)));
            return;
        }

        for(int i=0; i<n; i++){
            if(used[i]) continue;
            per[pos] = (char)('0'+(i+1));
            if(i==pos){
                if(n%2==0 || num==1) continue;
                else if(num==0){
                    used[i] = true;
                    dfs(pos+1,1);
                    used[i] = false;
                }
            }else{
                used[i] = true;
                dfs(pos+1,num);
                used[i] = false;
            }
        }
    }

    int dijkstra(String ss){
        //permutation,cost
        PriorityQueue<int[]> 
            q = new PriorityQueue<int[]>(n, new Comparator<int[]>(){
                    public int compare(int[] a, int[] b){
                        return a[1] - b[1];
                    }
                });

        q.add(new int[]{Integer.parseInt(ss),0});
        boolean[] v = new boolean[8765433];

        while(q.size()>0){
            int[] pp = q.poll();
            int perm = pp[0];
            int cost = pp[1];

            if(perm==goal) return cost;
            if(v[perm/10]) continue;
            v[perm/10] = true;

            char[] permm = Integer.toString(perm).toCharArray();

            for(int i=0; i<n; i++){
                for(int j=i+1; j<n; j++){
                    char tmp = permm[i];
                    permm[i] = permm[j];
                    permm[j] = tmp;
                    q.add(new int[]{Integer.parseInt(new String(permm)), cost+c[i][j]});
                    tmp = permm[i];
                    permm[i] = permm[j];
                    permm[j] = tmp;
                }   
            }
        }
        return -1;
    }

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