https://ac.nowcoder.com/acm/contest/5670/A
把一个任务分为两个任务,先到ai再到bi
设dp[i][u]为完成了i任务后,在u位置放了一个传送门的最小距离
那么有dp[i+1]四种转移方法,直接由a[i]走到a[i+1],由a[i]瞬移到u再走到a[i+1],先走到v然后瞬移回u再走到a[i+1]并把传送门放在v,由a[i]传送到u然后走到v再走到a[i+1]。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> p;
typedef long long ll;
const int maxl=610;
const ll inf=1ll<<60;
int n,m,k;ll ans;
int a[maxl],b[maxl];
int frm[maxl][maxl];
ll f[maxl][maxl];
ll dp[maxl][maxl];
bool in[maxl];
inline void prework()
{
scanf("%d%d%d",&n,&m,&k);
int u,v,w;
memset(f,0x3f,sizeof(f));
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
f[u][v]=min(f[u][v],1ll*w);
f[v][u]=min(f[v][u],1ll*w);
}
for(int i=1;i<=2*k;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
f[i][i]=0;
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
inline void mainwork()
{
memset(dp,0x3f,sizeof(dp));
dp[0][1]=0;a[0]=1;
for(int i=0;i<2*k;i++)
for(int u=1;u<=n;u++)
{
dp[i+1][u]=min(dp[i+1][u],dp[i][u]+f[a[i]][a[i+1]]);
dp[i+1][u]=min(dp[i+1][u],dp[i][u]+f[u][a[i+1]]);
for(int v=1;v<=n;v++)
{
dp[i+1][v]=min(dp[i+1][v],dp[i][u]+f[a[i]][v]+f[u][a[i+1]]);
dp[i+1][v]=min(dp[i+1][v],dp[i][u]+f[u][v]+f[v][a[i+1]]);
}
}
ans=dp[2*k][1];
for(int i=1;i<=n;i++)
ans=min(ans,dp[2*k][i]);
}
inline void print()
{
printf("%lld\n",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}