java自定義Scanner類似功能類的例項講解
阿新 • • 發佈:2020-08-21
題目描述
給定一張 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; }