POJ - 3311(floyd+状压dp)

题目:click
题意:找一条经过n个点回到0点的最小距离的路。
给定的邻接矩阵没有没有确定每两点之间的最短距离,由于每个点都可以重复多次计算,预先用floyd处理出最短路。再状压dp。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int MAXN=1e7+5;
int n;
int a[15][15];
int dp[15][(1<<12)];
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        int i,j,k;
        for(i=0;i<=n;i++)
        {
            for(j=0;j<=n;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        for(i=0;i<=n;i++)//中转节点
        {
            for(j=0;j<=n;j++)
            {
                for(k=0;k<=n;k++)
                {
                    a[j][k]=min(a[j][k],a[j][i]+a[i][k]);
                }
            }
        }
        int yyyy=(1<<n+1);
        memset(dp,inf,sizeof(dp));
        dp[0][(1<<i)]=0;
        for(i=1;i<=n;i++)
        {
            int temp=(1<<0)+(1<<i);
            dp[i][(1<<i)]=a[0][i];
        }
        for(i=0;i<yyyy;i++)
        {
            for(j=0;j<=n;j++)
            {
                if((1<<j)&i==0||dp[j][i]==inf)
                    continue;
                for(k=0;k<=n;k++)
                {
                    if(j==k)
                        continue;
                    if((1<<k)&i)
                    {
                        dp[k][i]=min(a[j][k]+dp[j][i],dp[k][i]);
                    }
                    else
                    {
                        int temp=(1<<k)|i;
                        dp[k][temp]=min(dp[k][temp],dp[j][i]+a[j][k]);
                    }
                }
            }
        }
        yyyy--;
        printf("%d\n",dp[0][yyyy]);
    }
    return 0;
}

发布了72 篇原创文章 · 获赞 19 · 访问量 7489

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/105245790