Niuke-Suburban Spring Outing (state compression dp) (java) (c++)

Topic link

This spring Tiezi’s class organized a spring outing. There are n suburbs and m undirected roads in the city of Tiezi. The i-th road connects the suburbs Ai and Bi, and the toll is Ci. After Tie Zi He Shun Liu’s proposal, they decided to go to R suburbs to play (regardless of the order of play), but because their class fees are tight, they need to find a tourist route to minimize their expenses, assuming they make a tour The route is V1, V2, V3… VR, then their total cost is the cost from V1 to V2 plus the cost from V2 to V3 and so on. Pay attention to the cost from iron class to V1 and from VR to iron class There is no need to consider the cost, because these two costs are reimbursed by the school and we do not plan to tell you the location of the Tiezi School.
Input description: The
first line of three integers n, m, R (2 ≤ n ≤ 200, 1 ≤ m ≤ 5000, 2 ≤ R ≤ min(n, 15)).
The R integers in the second row represent the number of the suburbs where you need to play.
The following m lines and each line Ai, Bi, Ci (1 ≤ Ai, Bi ≤ n, Ai ≠ Bi, Ci ≤ 10000)
ensure that there are no double edges.
Output description:
output one line to indicate the minimum cost

java code

import java.util.*;

 
public class Main {
    
    
 
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int R = sc.nextInt();
        int[][] dis = new int[n + 1][n + 1];
        for(int i = 0; i <= n; i++) {
    
    
            Arrays.fill(dis[i], Integer.MAX_VALUE);
            dis[i][i] = 0;
        }
 
        int[] tar = new int[R + 1];
        for(int i = 1; i <= R; i++) {
    
    
            tar[i] = sc.nextInt();
        }
        for(int i = 0; i < m; i++) {
    
    
            int x = sc.nextInt();
            int y = sc.nextInt();
            int c = sc.nextInt();
            dis[x][y] = c;
            dis[y][x] = c;
        }
        //floyd
        for(int k = 1; k <= n; k++) {
    
    
            for(int i = 1; i <= n; i++) {
    
    
                for(int j = i + 1; j <= n; j++) {
    
    
                    if(dis[i][k] != Integer.MAX_VALUE && dis[k][j] != Integer.MAX_VALUE) {
    
    
                        dis[i][j] = Math.min(dis[i][j], dis[i][k] + dis[k][j]);
                        dis[j][i] = dis[i][j];
                    }
                }
            }
        }
        dis[0][0] = 0;
        int s = 1 << R;
        int[][] dp = new int[s + 1][R + 1];
        for(int i = 0; i <= s; i++) {
    
    
            Arrays.fill(dp[i], Integer.MAX_VALUE);
        }
//        dp[0][0] = 0;
        //traverse all state
        for(int i = 1; i <= s; i++) {
    
    
 
            //choose the last arrived point
            for(int j = 1; j <= R; j++) {
    
    
                if(((i >> j - 1) & 1) > 0) {
    
    
                    //if the last arrived point is the only one
 
                    if(i == (1 << j - 1)) {
    
    
                        dp[i][j] = 0;
                    } else {
    
    
 
                        //traverse all point in this state
                        for(int k = 1; k <= R; k++) {
    
    
                            if(((i >> k - 1) & 1) > 0 && k != j) {
    
    
//                                dp[i][j] = Math.min(dp[i ^ k ^ j][k] + dis[tar[k]][tar[j]], dp[i][j]);
                                dp[i][j] = Math.min(dp[i ^ (1 << j - 1)][k] + dis[tar[k]][tar[j]], dp[i][j]);
 
                            }
                        }
                    }
                }
            }
        }
 
        int ans = Integer.MAX_VALUE;
        for(int i = 1; i <= R; i++) {
    
    
            ans = Math.min(ans, dp[(1 << R)- 1][i]);
        }
        System.out.println(ans);
    }
}

c++ code

#include  <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 205;
int e[maxn][maxn];
int n, m, r;
int reach[maxn];
int vis[maxn];
int ans = inf;
int dp[50000][20];
int main() {
    
    
    memset(e, inf, sizeof(e));
    scanf("%d%d%d", &n, &m, &r);
    for(int i = 1; i <= r; i++) {
    
    
        scanf("%d", &reach[i]);
    }
    for(int i = 1; i <= n; i++) e[i][i] = 0;
    for(int i = 1; i <= m; i++) {
    
    
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        e[u][v] = e[v][u] = min(e[u][v], w);
    }
    for(int k = 1; k <= n; k++) {
    
    
        for(int i = 1; i <= n; i++) {
    
    
            for(int j = 1; j <= n; j++) {
    
    
                if(e[i][j] > e[i][k] + e[k][j]) e[i][j] = e[i][k] + e[k][j];
            }
        }
    }
    memset(dp, inf, sizeof(dp));
    for(int i = 0; i < r; i++) dp[1 << i][i + 1] = 0;
    for(int s = 0; s < (1 << r); s++) {
    
    
        for(int i = 1; i <= r; i++) {
    
    
            if(s & 1 << (i - 1) == 0) continue;
            for(int j = 1; j <= r; j++) {
    
    
                if(s & 1 << (j - 1))continue;
                dp[s | 1 << (j - 1)][j] = min(dp[s | 1 << (j - 1)][j], dp[s][i] + e[reach[i]][reach[j]]);
            }
        }
    }
    int MIN = inf;
    int s = (1 << r) - 1;
    for(int i = 1; i <= r; i++) MIN = min(MIN, dp[s][i]);
    printf("%d\n", MIN);
    return 0;

Guess you like

Origin blog.csdn.net/jahup/article/details/105812587