1. 程式人生 > 實用技巧 >spring boot:用dynamic-datasource-spring-boot-starter配置多資料來源訪問seata(seata 1.3.0 / spring boot 2.3.3)

spring boot:用dynamic-datasource-spring-boot-starter配置多資料來源訪問seata(seata 1.3.0 / spring boot 2.3.3)

題目描述

給定一張 n 個點的帶權無向圖,點從 0 ~ n−1 標號,求起點 0 到終點 n−1 的最短 Hamilton 路徑。 Hamilton 路徑的定義是從 0 到 n−1 不重不漏地經過每個點恰好一次。

輸入格式

第一行輸入整數 n。
接下來 n行每行 n 個整數,其中第 i 行第 j 個整數表示點 i 到 j 的距離(記為 a[i,j])。
對於任意的 x,y,z,資料保證 a[x,x]=0,a[x,y]=a[y,x] 並且 a[x,y]+a[y,z]>=a[x,z]。

輸出格式

輸出一個整數,表示最短 Hamilton 路徑的長度。

資料範圍

1≤n≤20
0≤a[i,j]≤\(10^7\)

輸入樣例

5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0

輸出樣例

18

思路

程式碼

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=20,M=1<<20;//一共有2的20次方種情況
int f[M][N],weight[N][N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cin>>weight[i][j];//輸入點i與點j之間的距離
        }
    }
    memset(f,0x3f,sizeof(f));//由於要求最小值,所以這裡將 f 初始化為正無窮會更好處理一些(注意:memset函式是按照位元組進行賦值的)
    f[1][0]=0;//由於題目要求0點為起始點,所以0 -> 0的距離長度為0。對其初始化後方便接下來遞推的過程。
    for(int i=1;i<(1<<n);i++)
    {
        for(int j=0;j<n;j++)//列舉當前所在的點
        {
            if(i>>j&1)//判斷路徑i中是否包括當前點j,如果包括當前點,則可以進行狀態轉移(注意: >>運算子的優先順序高於&運算子的優先順序,所以(i>>j)&1可以寫成i>>j&1)
            {
                //要完成點k到點j的轉移,所以要來列舉k。
                for(int k=0;k<n;k++)
                {
                    if(i-(1<<j)>>k&1)//只有去除掉點j後路線中仍然包含點k才能說明路線是在點k的基礎上向點j轉移的(注意:算術運算子的優先順序大於位運算子的優先順序)
                    {
                        f[i][j]=min(f[i-(1<<j)][k]+weight[k][j],f[i][j]);
                    }
                }
            }
        }
    }
    cout<<f[(1<<n)-1][n-1]<<endl;//由於題目要求計算從點n到點n-1的路徑長度,所以(1<<n)-1的二進位制形式為111...111[共有n個1].
    /*
       f[i][j]中
       i的含義是當前的路徑(eg:5的二進位制形式為101,表示路徑經過點0和點2,不經過點1)
       j的含義是當前路徑的終點
    */
    return 0;
}