[状态压缩DP] PKU 3311 Hie with the Pie

和COJ送货到家一样,不过这里不要求每个点只经过一次,因此可以先用floyd预处理出任意两点间的最短距离,然后状态压缩DP。

# include <cstdio>

# include <cstring>



# define INF 0x3C3C3C3C

# define N 10 + 2



int n;

int w[N][N];

int f[1<<N][N];



int Min(int x, int y)

{

    return x<y ? x:y;

}



int dp(int s, int i)

{

    int &ans = f[s][i];

    if (ans != -1) return ans;

    int ns = s&(~(1<<i));

    if (ns == 1) return ans = w[0][i];

    ans = INF;

    for (int j = 1; j < n; ++j) if (((s>>j)&0x1) && j!=i)

    {

        ans = Min(ans, dp(ns, j)+w[j][i]);

    }

    return ans;

}



void solve(void)

{

    int ans = INF;

    if (n==1) {puts("0");return ;}

    for (int i = 0; i < (1<<n); ++i)

        memset(f[i], -1, sizeof(int)*n);

       f[1][0] = 0;

    for (int i = 1; i < n; ++i)

    {

        ans = Min(ans, dp((1<<n)-1, i)+w[i][0]);

    }

    printf("%d\n", ans);

}



void read_graph(void)

{

    for (int i = 0; i < n; ++i)

    for (int j = 0; j < n; ++j)

        scanf("%d\n", &w[i][j]);

}



void rebuild_graph(void)

{

    for (int k = 0; k < n; ++k)

    for (int i = 0; i < n; ++i)

    for (int j = 0; j < n; ++j)

        w[i][j] = Min(w[i][j], w[i][k]+w[k][j]);        

}



int main()

{    

    while (scanf("%d", &n), n)

    {

        ++n;

        read_graph();

        rebuild_graph();

        solve();

       }

           

    return 0;

}

你可能感兴趣的:(with)