一开始得思路有一点小问题,把他想成最小生成树+floyd算法来做了,但是再状态得重复上以及往回走得vis判断上出现了问题,我就觉得思路不对了,看了下题解,用的时floyd算法求最短路,然后利用Dp遍历状态,求总体的最短路,也算借助此机会复习了一下最短路了(悲催的时,最短路得学习过程中,就忽略了暴力得floyd得学习(转载……))
Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)
从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们
检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们
便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
好了,现在我们学会了Floyd算法,先来针对输入,把任意两点之间得最短路求出来吧
for(int i = 0;i <= N;i++)//中间点得遍历 { for(int j = 0;j <= N;j++) //对应该中间的得起点得遍历 { for(int k = 0;k <= N;k++)//对应终点得遍历 { if(cost_mp[j][i] + cost_mp[i][k] < cost_mp[j][k]) cost_mp[j][k] = cost_mp[j][i] + cost_mp[i][k]; } } }
针对所有的状态,层层向上更新状态中的最短路进问题即Dp[state][i]数组问题,再state状态下,我要到i城市i取得最短路是多少,如果这个状态仅仅包含一个城市i,那么就是cost_mp【state】[i],包含至少两个城市,就要看看路径更新的问题了,遍历所有可能的中间城市,进行路径更新……
for(int i = 0;i < (1 << N);i++)//所有状态
{
for(int j = 1;j <= N;j++)//所有城市
{
if(i & (1 << (j - 1)))//状态s中已经有了城市j了,寻找得是到j城得最短路
{
if(i == (1 << (j - 1)))//仅有i这一个城市
{
dp[i][j] = cost_mp[0][j];
}
else//不仅仅只有i这一个城市
{
dp[i][j] = inf;//初始化
for(int k = 1;k <= N;k++)//寻找状态中包含的第二个城市,即中间城市
{
if(i & (1 << (k - 1)) && k != j)//更新
dp[i][j] = min(dp[i^(1 << (j - 1))][k] + cost_mp[k][j],dp[i][j]);
//i^(1 << (j - 1)表示i中得不包含j得子集,因为要到j城市去嘛,所以集合中不能走过k城,才能尝试更新最短路
}
}
}
}
}
int ret = dp[(1 << N) - 1][1] + cost_mp[1][0];//状态是所有的城市都走过后,从哪一个城市到披萨店最近
for(int i = 2;i <= N;i++)
{
if(dp[(1 << N) - 1][i] + cost_mp[i][0] < ret)
ret = dp[(1 << N) - 1][i] + cost_mp[i][0];
}