Portal
您现在在一家大工厂里。可以将工厂看作为具有n个顶点和m个边的图。每个边都有其长度。您有k个任务要做。第i个任务为达顶点a_i,拾取一个块,然后将其发送到顶点b_i。您应该按照从1号到k号的顺序完成任务。最初,您站在顶点1。
你手里拿着枪。当您处于某个顶点u时,您可以向地面射击,然后将在顶点u建立一个传送门。当工厂中有两个传送门时,假设它们分别位于u和v处,则可以在u和v之间进行瞬间转移(就像连接长度为0的u和v的边一样)。
您的手边还有一个遥控器。它使您可以随时随地关闭传送门(一次关闭一个传送门,而不是一次关闭所有传送门)。并且,最多可以有两个现有传送门。因此,如果要在存在两个传送门时创建另一个传送门,则必须先使用控制器将其关闭,然后再创建。您需要找到必须步行的最小距离才能完成所有k个任务。

动态规划。dp[i][j] i表示是第i组任务,j表示传送门的位置

#include<bits/stdc++.h>
using namespace std;
long long dp[800][500],f[800][500],t[10050];
int main (){
long long n,m,k;
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=0;i<=700;++i) for(int j=1;j<=400;++j) dp[i][j]=1ll<<60,f[i][j]=1ll<<60;
for(int i=1;i<=n;++i) f[i][i]=0;
for(long long i=1;i<=m;++i){
    long long x,y,z;
    scanf("%lld%lld%lld",&x,&y,&z);
    f[x][y]=f[y][x]=min(f[x][y],z);
}
int cnt=0;

for(long long k=1;k<=n;++k)for(long long i=1;i<=n;++i)for(long long j=1;j<=n;++j)f[i][j]=min(f[i][k]+f[k][j],f[i][j]);//folyd 求最短路

for(long long i=1;i<=k;++i){
    long long ta,tt;
    scanf("%lld%lld",&ta,&tt);//建造任务
    t[++cnt]=ta; t[++cnt]=tt;
}
dp[0][1]=0;//超级任务
k*=2;
t[0]=1;
for(long long i=1;i<=k;++i){
    for(long long j=1;j<=n;++j){
        dp[i][j]=min(dp[i][j],dp[i-1][j]+f[t[i-1]][t[i]]);//直接从c[i]走到c[i+1]

        for(long long l=1;l<=n;++l){
            dp[i][j]=min(dp[i][j],dp[i-1][l]+f[l][t[i]]+f[t[i-1]][j]);//第二种转移是从c[i]走到q,在q设置传送门,从q传送到p,再从p走到c[i+1]
            dp[i][l]=min(dp[i][l],dp[i-1][j]+f[j][l]+f[l][t[i]]);//第三种转移是从c[i]传送到p,从p走到q,在q设置传送门,最后从q走到c[i+1]

        }
    }
}
long long ans=1ll<<60;
for(long long i=1;i<=n;++i) ans=min(ans,dp[k][i]);
cout<<ans<<endl;

}