精!神!污!染!
这题就是传说中的TSP问题。
TSP问题也就是最小哈密顿回路问题
在这题中,这里的图为完全图,所以我们不用邻接表,可以用邻接矩阵。
先来一种暴力做法,复杂度为
Θ
(
n
∗
n
!
)
\Theta(n*n!)
Θ(n∗n!)
#include<iostream>
using namespace std;
int a[41][41],vis[41],ans=2147483647,n;
void dfs(int i,int j,int l)
{
if(j>ans) return;
if(l==n&&j<ans)
{
ans=j;
return;
}
for(int k=1;k<=n;k++)
if(i!=k&&!vis[k])
{
vis[k]=1;
dfs(k,j+a[i][k],l+1);
vis[k]=0;
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
dfs(1,0,0);
cout<<ans;
}
别抄,有坑
然鹅,这题
n
<
20
n<20
n<20的洛谷要求,让这题承受不起。
接下来,我们得进行如下剪枝:
如果目前累加的值已大于答案,那就立即回溯。
如果目前所有未搜的点加目前的值大于答案,就立即回溯。
然后一波乱搞就能过。
代码 不是我写的,题解里抄的
正解
这题其实是状压DP。
设
F
[
i
,
j
]
F[i,j]
F[i,j]表示状态
i
i
i时目前搜索到第
j
j
j个。
容易的到状态转移方程:
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
d
p
[
i
x
o
r
1
<
<
j
]
[
k
]
+
a
[
k
]
[
j
]
)
;
dp[i][j]=min(dp[i][j],dp[{i\quad xor \quad1}<<j][k]+a[k][j]);
dp[i][j]=min(dp[i][j],dp[ixor1<<j][k]+a[k][j]);
代码:
#include<iostream>
#include<cstring>
using namespace std;
int dp[1<<20][20],a[21][21],b,ans=2147483647;
int main()
{
memset(dp,0x7f,sizeof(dp));
cin>>b;
for(int i=0;i<b;i++)
for(int j=0;j<b;j++)
cin>>a[i][j];
dp[1][0]=0;
for(int i=1;i<1<<b;i++)
for(register int j=0;j<b;j++)
if(i&1<<j)for(register int k=0;k<b;k++)
if(j!=k&&i&1<<k) dp[i][j]=min(dp[i][j],dp[i^1<<j][k]+a[k][j]);
for(int i=1;i<b;i++) ans=min(dp[(1<<b)-1][i]+a[i][0],ans);
cout<<ans;
}
目前学校OJ稳居Rank1