题意:一开始就在旅游的几个点选一个作为起点,然后这个点就算游过了,游完别的景点在最后一个景点停下即可。
用dp[i][j],i表示状态(哪些点游过,哪些点没有),j表示最后停留在哪个点。
具体看代码详细注释:

#include <bits/stdc++.h>
using namespace std;
int n,m,r;
const int N=205;
const int INF=0x3f3f3f3f;
int rs[18];//表示必须要旅游的点
int mp[N][N];
int dp[34000][20];
void floyed()
{
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++) mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&r);
    for(int i=1;i<=r;i++) scanf("%d",&rs[i]);
    memset(mp,INF,sizeof(mp));
    memset(dp,INF,sizeof(dp));
    while(m--)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        mp[u][v]=mp[v][u]=w;
    }
    floyed();
    for(int i=1;i<=r;i++)
    {
        dp[1<<(i-1)][i]=0; //最开始走的那一个点,是没有花费的
    }
    int len=(1<<r)-1;
    for(int i=1;i<len;i++)//枚举状态
    {
        for(int j=1;j<=r;j++)//枚举起始位置
        {
            int jj=1<<(j-1);
            if(!(i&jj)) continue;//起始位置肯定是走过的
            for(int k=1;k<=r;k++)//枚举终止位置
            {
                int kk=1<<(k-1);
                if(i&kk) continue;//终止位置一定是一个新位置
                dp[i|kk][k]=min(dp[i|kk][k],dp[i][j]+mp[rs[j]][rs[k]]);
            }
        }
    }
    int ans=INF;
    for(int i=1;i<=r;i++)
    {
        ans=min(ans,dp[len][i]);
    }
    printf("%d\n",ans);

}