精!神!污!染!
这题就是传说中的TSP问题。
TSP问题也就是最小哈密顿回路问题
在这题中,这里的图为完全图,所以我们不用邻接表,可以用邻接矩阵。
先来一种暴力做法,复杂度为
#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;
}
别抄,有坑
然鹅,这题的洛谷要求,让这题承受不起。
接下来,我们得进行如下剪枝:
如果目前累加的值已大于答案,那就立即回溯。
如果目前所有未搜的点加目前的值大于答案,就立即回溯。
然后一波乱搞就能过。
代码 不是我写的,题解里抄的
正解
这题其实是状压DP。
设表示状态时目前搜索到第个。
容易的到状态转移方程:
代码:
#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
来源:CSDN
作者:ssl_cxy
链接:https://blog.csdn.net/weixin_45523071/article/details/103617806