https://www.nowcoder.com/questionTerminal/3d1adf0f16474c90b27a9954b71d125d
public static void main(String[] args) {
int n = reader.nextInt();// 城市数目
int[][] dist = new int[n][n]; // 距离矩阵,距离为欧式空间距离
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
dist[i][j] = reader.nextInt();
int V = (1 << (n - 1)) - 1;// 对1进行左移n-1位,值刚好等于2^(n-1)
// dp表,n行,2^(n-1)列
int[][] dp = new int[n][V + 1];
// 初始化dp表第一列
for (int i = 0; i < n; i++) dp[i][0] = dist[i][0];
//设想一个数组城市子集V[j],长度为V,且V[j] = j,对于V[j]即为压缩状态的城市集合
//从1到V-1 用二进制表示的话,刚好可以映射成除了0号城市外的剩余n-1个城市在不在子集V[j],1代表在,0代表不在
//若有总共有4个城市的话,除了第0号城市,对于1-3号城市
//111 = V-1 = 2^3 - 1 = 7 ,从高位到低位表示3到1号城市都在子集中
//而101 = 5 ,表示3,1号城市在子集中
for (int j = 1; j <= V; j++) //这里j不仅是dp表的列坐标值,如上描述,j的二进制表示城市相应城市是否在子集中
for (int i = 0; i < n; i++) { //这个i不仅代表城市号,还代表第i次迭代
dp[i][j] = Integer.MAX_VALUE; //为了方便求最小值,先将其设为最大值
if (((j >> (i - 1)) & 1) == 0) { //表示路径中不能有i号
for (int k = 1; k < n; k++) {
if (((j >> (k - 1)) & 1) == 1) { //遍历城市子集 路径j
//状态转移方程,例,dp[0][3] = dp[0][101] =
// max(dp[0][3], dis[0][1]+dp[1][100], dis[0][3]+dp[3][001])
dp[i][j] = Math.min(dp[i][j], dist[i][k] + dp[k][j ^ (1 << (k - 1))]); //^异或
}
}
}
}
System.out.println(dp[0][V]);
}
Comments | 0 条评论