核心思路:
1 找到当前状态,即当前被用过的点。
2 当前所处的位置。
用一个二维数组保存f[state][j];
state 就是当前状态,通过二进制状态压缩进行表示,例如有二十组,用1<<20-1;表示状态已满。
j 就是当前点的位置。
通过每次判断当前位置是否遍历用state>>j&1;
然后再判断上一次的经过的点,寻找最小值,最后f[1<<20-1][20-1]就是所求的答案。
代码:
#include
#include
#include
using std::cin;
using std::cout;
using std::endl;
using std::min;
const int M=1<<20,N=20;
int f[M][N];//表示当前点的最小值
int weight[N][N];//存储权值
int main(void)
{
int n;
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>weight[i][j];
memset(f,0x3f,sizeof(f));//初始化最大值
f[1][0]=0;//第一个数路径为零
for(int i=1;i<1<<n;i++)
for(int j=0;j<n;j++)
if(i>>j&1)//判断 是否经过当前点
for(int k=0;k<n;k++)
if((i^1<<j)>>k&1)//判断经历的前一个点,状态为1都可以参与计算
f[i][j]=min(f[i][j],f[i^1<<j][k]+weight[k][j]);//求最小值
cout<<f[(1<<n)-1][n-1]<<endl;
return 0;
}
补充一下小知识:
lowbit 运算
求一个数的二进制的最后一个数值为一所在的位置。
eg:x=10010010;
对其求反~x=01101101;
再加一 ~x+1=01101110;
最后 result=x&(~x+1)=00000010;
log2(result)即为结果。
lowbit运算就是result=x&(~x+1);
在计算机中~x+1=-x;
即lowbit=x&-x;