题目: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[1005],c[205][205],d[2][205][205],ans=2000005; int main() { scanf("%d%d",&l,&n); for(int i=1;i<=l;i++) for(int j=1;j<=l;j++) scanf("%d",&c[i][j]); memset(d[1],11,sizeof d[1]); scanf("%d",&q[1]); d[1][1][2]=c[3][q[1]];d[1][1][3]=c[2][q[1]];d[1][2][3]=c[1][q[1]]; for(int i=2;i<=n;i++) { // printf("i=%d ",i); memset(d[i%2],11,sizeof d[i%2]); scanf("%d",&q[i]); for(int j=1;j<l;j++) for(int k=j+1;k<=l;k++) { if(j==q[i-1]||k==q[i-1])continue; d[i%2][j][k]=min(d[i%2][j][k],d[(i-1)%2][j][k]+c[q[i-1]][q[i]]); if(q[i-1]==q[i])continue; int a=min(q[i-1],k),b=max(q[i-1],k); d[i%2][a][b]=min(d[i%2][a][b],d[(i-1)%2][j][k]+c[j][q[i]]); a=min(q[i-1],j);b=max(q[i-1],j); d[i%2][a][b]=min(d[i%2][a][b],d[(i-1)%2][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 ",q[i],j,k,d[i][j][k]); } for(int i=1;i<l;i++) for(int j=i+1;j<=l;j++) ans=min(ans,d[n%2][i][j]); printf("%d",ans); return 0; }