AcWing 91. java同学详解
原题链接
中等
作者:
季之秋
,
2021-02-19 18:23:05
,
所有人可见
,
阅读 190
/*
状态压缩,f[i][j] i表示第几位上的数是否走过: 第0位表示0是否走过,第1位表示1是否走过
j表示最终走到j点,例如:f[5(000101)][7]表示 走过 0 2 最终走到 7 的距离(因为不包含7 所以不可取)
f[1][0]=0初始化 :因为在0点开始且停留在0点所以j=0 , 第0位走过所以 i = 000001,并且0到0的距离=0
用最后一个到j的点k来转移,i去掉j这个点( i - 1<<j ) 就是i到k的距离 ,走到终点为k ——>f[i-1<<j][k]
加上k到j的距离(w[k][j]) 就能转移状态;
前提要保证i中有j , i-(1<<j)中有k才能走到终点,否则状态无效;
*/
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(),N=21,M=1<<N,INF=Integer.MAX_VALUE>>1;
int[][] w=new int[N][N],f=new int[M][N];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
w[i][j]=sc.nextInt();
}
}
for(int i=0;i<M;i++)
Arrays.fill(f[i],INF); //判断最小值 以max fill
f[1][0]=0; //初始化状态
for(int i=1;i<(1<<n);i++) //每个状态
for(int j=1;j<n;j++) //每个终点
if(((i>>j)&1)==1) //包含终点才成立
for(int k=0;k<n;k++)
if(((i-(1<<j)>>k)&1)==1) //包含k才可以转移
f[i][j]=Math.min(f[i][j],f[i-(1<<j)][k]+w[k][j]); // 用倒数第二个点k转移
System.out.println(f[(1<<n)-1][n-1]); //输出每个点都走过且终点是n-1的路径和
//因为取min,所以不存在每个点都走了的情况下还有某个点走几遍的情况出现,那样的肯定不是最小值
}
}