POJ 3311 Hie with the Pie(Floyd + 状压dp)

思路:

  • 首先要求出多源最短路,floyd直接上
  • 然后是我们要求的,哈密顿回路的一个变种,咱们的题目要求的是把每个点都走一遍回到起点,但是与哈密顿回路不同的是,每个点可以走多次。(所以可以用floyd先把所有边都压缩一边)
  • 所以我们需要一个代表状态的数,本题最多11个点,所以我们至少需要11位的二进制数来表示。第i位代表着第i个节点是否已经走过。
  • 除了需要已经走过的信息,我们还需知道当前的位置,所以加一维。 dp[s][i] 表示在s的状态下,当前在i点所走的最短距离。

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;

int n;
int dp[(1L<<11)+10][14];
int a[22][22];
void floyd(){
    for(int k = 0;k <= n;k++){
        for(int i = 0;i <= n;i++){
            for(int j = 0;j <= n;j++){
                if(a[i][j] > a[i][k] + a[k][j]){
                    a[i][j] = a[i][k] + a[k][j];
                }
            }
        }
    }
}
int main(){
    while(~scanf("%d",&n),n){
        for(int i = 0;i <= n;i++){
            for(int j = 0;j <= n;j++){
                scanf("%d",&a[i][j]);
            }
        }
        floyd();
        int flag = (1<<(n+1)) - 1;
        memset(dp,0x3f,sizeof(dp));
        for(int i = 0;i <= n;i++){//边界条件
            dp[1][i] = a[0][i];//dp[0][i]是不能走到的,所以赋无穷大
        }
        int s;
        for(s = 1;s <= flag;s++){
            for(int i = 0;i <=n;i++){
                if(s == (1<<i)) dp[s][i] = a[0][i];//边界条件,但其实这种状态并不符合条件,只是要作为边界
                for(int j = 0;j <=n;j++){
                    if(i!=j && (s&(1<<j)))
                        dp[s][i] = min(dp[s&(~(1<<j))][j]+a[j][i],dp[s][i]);
                }
            }
        }
        int ans = 0x7f7f7f7f;
        for(int i = 0;i <= n;i++){
            ans = min(ans,dp[s-1][i]+a[i][0]);
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值