Spring outing in the suburbs

Suburban spring outing

Meaning:
give nnn places,mmm roads, each road has a weightvvv R R Where R want to go, ask how to arrange the itinerary to minimize the cost.

Idea:
First we use F loyd (O (n 3)) Floyd(O(n^3))Floyd(O(n3 ))Find the minimum cost of each two places.
Because ofRRThe value range of R is[2, 15] [2, 15][ 2 , 1 5 ] , we can use binary bits(0 or 1) (0or1)( 0 o r 1 ) to indicate whether a location has been visited, for example,6 = (0110) 2 6=(0110)_26=(0110)2, It means that we have visited the first and second places.
Then we use dp [i] [j] dp[i][j]d p [ i ] [ j ] to representi, ji, ji,The minimum cost in j state. Whereiii is the binary representation mentioned above,jjj means at the momentjjj positions (note dp initialization).
Now is the state transition:
dp [i + (1 <<k)] [k] = min (dp [i + 1 <<k] [k], dp [i] [j] + F [g [j] [g [k]] dp[i+(1<<k)][k] = min(dp[i+1<<k][k], dp[i][j]+F[g[j][ g[k]]dp[i+(1<<k)][k]=min(dp[i+1<<k][k],dp[i][j]+F [ g [ j ] [ g [ k ] ]
The meaning of the equation is whether to pass the statedp [i] [j] dp[i][j]dp[i][j]达到 d p [ i + ( 1 < < k ) ] [ k ] dp[i+(1<<k)][k] dp[i+(1<<k ) ] [ k ] state (choose the less expensive one). Wherei + (1 <<k) i+(1<<k)i+(1<<k ) , i does not pass the kth place, wheni + (1 <<k) i+(1<<k)i+(1<<k ) after the firstkkk positions will become1 11

We will iii is in the interval[1, 2 r − 1] [1,2^r-1][1,2r1 ] Enumerate, enumerate each selection state. jjj andkkk is in the interval[0, r] [0, r][0,r]上枚举。
最后取 m a x ( d p [ ( 1 < < r ) − 1 ] [ i ] ) ( i ∈ [ 0 , r ] ) max(dp[(1<<r)-1][i])(i\in[0, r]) max(dp[(1<<r)1][i])(i[0,r])

C o d e Code Code

#include<bits/stdc++.h>
using namespace std;
const int inf = 1<<23;
const int N = 20;
const int M = 210;
int g[N], F[M][M], dp[1 << 15][20];
int main() {
    
    
    int n, m, r, a, b, c;
    cin >> n >> m >> r;
    for(int i=0; i<r; i++) cin >> g[i];
    //初始化F数组
    for(int i=1; i<=n; i++) {
    
    
        for(int j=1; j<=n; j++) {
    
    
            if(i != j) F[i][j] = inf;
        }
    }
    //读入每条路径
    for(int i=0; i<m; i++) {
    
    
        cin >> a >> b >> c;
        F[a][b] = min(F[a][b], c);
        F[b][a] = F[a][b];
    }
    //floyd求两点之间最小花费
    for(int i=1; i<=n; i++) {
    
    
        for(int j=1; j<=n; j++) {
    
    
            for(int k=1; k<=n; k++) {
    
    
                F[j][k] = min(F[j][k], F[j][i] + F[i][k]);
            }
        }
    }
    //初始化dp数组
    memset(dp, 0x7f, sizeof dp);
    for(int i=0; i<r; i++) {
    
    
        dp[1 << i][i] = 0;
    }
    //枚举i,j,k。状态转移
    for(int i=1; i<(1 << r)-1; i++) {
    
    
        for(int j=0; j<r; j++) {
    
    
            if(i & (1 << j)) {
    
    
                for(int k=0; k<r; k++) {
    
    
                    if(!(i & (1 << k))) 
                    dp[i + (1 << k)][k] = min(dp[i + (1 << k)][k], dp[i][j] + F[g[j]][g[k]]);
                }
            }
        }
    }
    //取最大值,得到答案。
    int ans = inf;
    for(int i=0; i<r; i++) {
    
    
        ans = min(ans, dp[(1 << r)-1][i]);
    }
    cout << ans;
    return 0;
}


Guess you like

Origin blog.csdn.net/weixin_45363113/article/details/108063719