Floyd & 状压DP —— poj331

一开始得思路有一点小问题,把他想成最小生成树+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];
        }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值