题目:http://www.joyoi.cn/problem/tyvj-1061
dp。枚举三个人现在的位置。
1.重点:当前必有一人正处在查询点上!于是省掉一维。
2.转移方程枚举上一阶段的 j 和 k 的位置比较好想。
3.通过 j < k 的限制避免重复。
4.转移的时候对于条件的小小注意。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int l,n,q[],c[][],d[][][],ans=;
int main()
{
scanf("%d%d",&l,&n);
for(int i=;i<=l;i++)
for(int j=;j<=l;j++)
scanf("%d",&c[i][j]);
memset(d[],,sizeof d[]);
scanf("%d",&q[]);
d[][][]=c[][q[]];d[][][]=c[][q[]];d[][][]=c[][q[]];
for(int i=;i<=n;i++)
{
// printf("i=%d\n",i);
memset(d[i%],,sizeof d[i%]);
scanf("%d",&q[i]);
for(int j=;j<l;j++)
for(int k=j+;k<=l;k++)
{
if(j==q[i-]||k==q[i-])continue;
d[i%][j][k]=min(d[i%][j][k],d[(i-)%][j][k]+c[q[i-]][q[i]]);
if(q[i-]==q[i])continue;
int a=min(q[i-],k),b=max(q[i-],k);
d[i%][a][b]=min(d[i%][a][b],d[(i-)%][j][k]+c[j][q[i]]);
a=min(q[i-],j);b=max(q[i-],j);
d[i%][a][b]=min(d[i%][a][b],d[(i-)%][j][k]+c[k][q[i]]);
}
// for(int j=1;j<l;j++)
// for(int k=j+1;k<=l;k++)
// printf(" q=%d j=%d k=%d d=%d\n",q[i],j,k,d[i][j][k]);
}
for(int i=;i<l;i++)
for(int j=i+;j<=l;j++)
ans=min(ans,d[n%][i][j]);
printf("%d",ans);
return ;
}