POJ 2288 Islands and Bridges (Java实现)

版权声明: https://blog.csdn.net/moon_sky1999/article/details/85240740

题目来源:http://poj.org/problem?id=2288

状压dp。f[i][j][k]表示状态为i时,上一条边为(j,k),这样记录了路径上之前两个结点的信息,就能进行修改。

注意特判n==1的情况,最终结果应该/2。

转移的过程中记录满足要求的路径数,当且仅当当前状态可以到达时再用其进行状态转移。

代码:

import java.io.*;
import java.lang.*;
import java.rmi.*;
import java.util.*;
import java.math.*;

public class Main {

    static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    static int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    static double nextDouble() throws IOException {
        in.nextToken();
        return in.nval;
    }

    static long nextLong() throws IOException {
        in.nextToken();
        return (long) in.nval;
    }

    static String next() throws IOException {
        in.nextToken();
        return in.sval;
    }

    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

    static int n, m;
    static long v[];
    static boolean g[][];
    static long f[][][];
    static long t[][][];
    static final long inf = 1000000010;

    static long Min(long a, long b) {
        return a < b ? a : b;
    }

    public static void main(String[] args) throws IOException {
        v = new long[15];
        g = new boolean[15][15];
        f = new long[(1 << 13)][14][14];
        t = new long[(1 << 13)][14][14];
        int T;
        T = nextInt();
        while (T-- != 0) {
            n = nextInt();
            m = nextInt();
            for (int i = 1; i < (1 << n); ++i) {
                for (int j = 1; j <= n; ++j) {
                    for (int k = 1; k <= n; ++k) {
                        f[i][j][k] = t[i][j][k] = 0;
                    }
                }
            }
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    g[i][j] = false;
                }
            }
            for (int i = 1; i <= n; ++i) {
                v[i] = nextLong();
            }
            for (int i = 1; i <= m; ++i) {
                int x, y;
                x = nextInt();
                y = nextInt();
                g[x][y] = g[y][x] = true;
            }
            if (n == 1) {
                out.print(v[1]);
                out.print(' ');
                out.println(1);
                continue;
            }
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    if (i != j && g[i][j]) {
                        f[(1 << (i - 1) | (1 << (j - 1)))][i][j] = f[(1 << (i - 1) | (1 << (j - 1)))][j][i] = v[i] + v[j] + v[i] * v[j];
                        t[(1 << (i - 1) | (1 << (j - 1)))][i][j] = t[(1 << (i - 1) | (1 << (j - 1)))][j][i] = 1;
                    }
                }
            }
            for (int i = 1; i < (1 << n); ++i) {
                for (int j = 1; j <= n; ++j)
                    if (((1 << (j - 1)) & i) != 0) {
                        for (int k = 1; k <= n; ++k)
                            if (k != j && ((1 << (k - 1)) & i) != 0 && g[j][k] && t[i][j][k] > 0) {
                                for (int p = 1; p <= n; ++p) {
                                    if (((1 << (p - 1)) & i) == 0 && g[k][p]) {
                                        long c = v[p] + v[k] * v[p];
                                        if (g[j][p]) c += v[j] * v[k] * v[p];
                                        if (f[i | (1 << (p - 1))][k][p] < f[i][j][k] + c) {
                                            f[i | (1 << (p - 1))][k][p] = f[i][j][k] + c;
                                            t[i | (1 << (p - 1))][k][p] = t[i][j][k];
                                        } else if (f[i | (1 << (p - 1))][k][p] == f[i][j][k] + c) {
                                            t[i | (1 << (p - 1))][k][p] += t[i][j][k];
                                        }
                                    }
                                }
                            }
                    }
            }
            long ans = 0;
            long tot = 0;
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j)
                    if (i != j && g[i][j]) {
                        if (ans < f[(1 << n) - 1][i][j] && t[(1 << n) - 1][i][j] != 0) {
                            ans = f[(1 << n) - 1][i][j];
                            tot = t[(1 << n) - 1][i][j];
                        } else if (ans == f[(1 << n) - 1][i][j]) {
                            tot += t[(1 << n) - 1][i][j];
                        }
                    }
            }
            if (tot == 0) {
                out.println("0 0");
            } else {
                out.print(ans);
                out.print(' ');
                out.println(tot / 2);
            }
        }
        out.flush();
    }
}

猜你喜欢

转载自blog.csdn.net/moon_sky1999/article/details/85240740
今日推荐