codevs 2800 送外卖(状压dp)

/*
f[i][j] 表示走过的点构成i状态 且最后到达的点为j时的最优解
在那最后一个状态就是(1<<n+1)-1 每个点都到达 在由此回到0 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010//最少到 1<<16 
using namespace std;
int n,g[20][20],f[maxn][20],ans=0x3f3f3f3f;
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
      for(int j=0;j<=n;j++)
        scanf("%d",&g[i][j]);
    for(int k=0;k<=n;k++)
      for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
          g[i][j]=min(g[i][k]+g[k][j],g[i][j]);
    memset(f,127/3,sizeof(f));f[1][0]=0;//初始化 
    for(int i=1;i<=(1<<n+1)-1;i++)//枚举走过点构成的状态 
      for(int j=0;j<=n;j++)//枚举最后一次到达的点 
        if((1<<j)&i)//j 走过了 
          {
              for(int k=0;k<=n;k++)
              f[i|(1<<k)][k]=min(f[i|(1<<k)][k],f[i][j]+g[j][k]); 
          }
    for(int i=1;i<=n;i++)
      ans=min(ans,g[i][0]+f[(1<<n+1)-1][i]);
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5768548.html