题目:
知识点:
i^(1<<j) : 表示将i的第j位取反
i>>j & 1 : 取出二进制下i的第j位
思路:
使用一个f数组,一维表示点经过点状态,二维表示目前处于该点的最短路径。
使用二进制表示点的状态,然后遍历数组中所有的点的状态
在某一个状态下,比如此时状态是1101,并且目前处于从左到右第二个1,
此时的最短路径就是,在1001的状态下,最左端的1和最右端的1到达从左到右第二个1的最小值
算出所有的这种状态,即可求出最短路径。
解答:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin>>n;
int weight[n][n];
int i,j,k;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
cin>>weight[i][j];
int f[1<<n][n]; //一维表示点经过点状态,二维表示目前处于该点的最短路径
memset(f,0x3f,sizeof(f)); //这设最短路径都是最大值
f[1][0]=0;
for(i = 1 ; i < 1<<n ; i++)
{
for(j = 0 ; j < n ; j++) // 遍历每一个可能的状态,在该状态下进行如下循环
{
if(i>>j & 1) // 如果i的第j位是1,表明该位已经经过,但是看看有没有更短路径
for(k=0;k<n;k++)
{
if((i^1<<j) >> k & 1) // 若i的第j位是0的状态下的第k位是1,因为第j位想为1,肯定是从其他位置的1走到第j位的1
{
if(f[i][j] > f[i^ 1<<j][k] + weight[k][j])
f[i][j]= (f[i^1<<j][k] + weight[k][j]);
}
}
}
}
// cout<<f[(1<<n)-1][n-1];
printf("%d",f[(1<<n)-1][n-1]);
}
// 总结
// i^(1<<j) : 表示将i的第j位取反
// i>>j & 1 : 取出二进制下i的第j位