题目描述
状态压缩DP(优化dfs的好方法)
状态表示:
f[i,j]
:所有从0
走到j
,走过得所有点是i
(i
是状态压缩的值,存所有走过的点)的所有路径
状态计算(划分依据
):枚举走的倒数第2个点是k
( k = 0~n-1)f[i][j] = f[i-{j},k] + w[k][j]
;时间复杂度:DP的时间复杂度计算:状态数量 × 状态转移( 2 20 2^{20} 220 * 20 * 20)
总结:
状态压缩:i
是状态压缩,存所有走过的点
划分依据:枚举倒数第2个点走的是哪个点
状态要有意义,如i >> j & 1
,(i - (1<<j)) >> k & 1
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20, M = 1<<N;
int n;
int w[N][N];
int f[M][N];
int main()
{
cin >> n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin >> w[i][j];
memset(f,0x3f,sizeof f);
f[1][0] = 0; // 从0走到0,状态包含0,路径为0
for(int i=0;i< 1<<n;i++)
for(int j=0;j<n;j++)
if(i >> j & 1) // 从0走到j,状态i得先包含j这个点
for(int k=0;k<n;k++)
if((i - (1<<j)) >> k & 1) // 同理,从k转移到j,得在状态i-{j}里包含k
f[i][j] = min(f[i][j],f[i - (1<<j)][k] + w[k][j]);
cout<<f[(1<<n)-1][n-1]<<endl;
return 0;
}