很不错的一道dp题
果然lyd学长书里的dp题质量超高
f[i][j][k]表示当前位置分别为a[i],j,k的最小花费
这样不仅包含了当前考虑到的是第几个,还把位置也包含了
考虑直接转移:$f[i][j][k]=min(f[i-1][……][……]+g[……][a[i]])$
注意初始化时增加a[0]=1,表示1,2,3状态值为0
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 1009
#define L 209
#define INF 32133493
int l,n,g[L][L],ans;
int f[N][L][L],a[N];
int main()
{
scanf("%d%d",&l,&n);
for(int i=1;i<=l;i++)
for(int j=1;j<=l;j++)
scanf("%d",&g[i][j]);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
a[0]=1;
for(int i=0;i<=n;i++)
for(int j=1;j<=l;j++)
for(int k=1;k<=l;k++)
f[i][j][k]=INF;
f[0][2][3]=0;
for(int i=1;i<=n;i++)
{
for(int x=1;x<=l;x++)
{
for(int y=1;y<=l;y++)
{
int z=a[i-1];
if(z!=a[i]&&y!=a[i]) f[i][y][z]=min(f[i][y][z],f[i-1][x][y]+g[x][a[i]]);
if(z!=a[i]&&x!=a[i]) f[i][x][z]=min(f[i][x][z],f[i-1][x][y]+g[y][a[i]]);
if(x!=a[i]&&y!=a[i]) f[i][x][y]=min(f[i][x][y],f[i-1][x][y]+g[z][a[i]]);
}
}
}
ans=INF;
for(int i=1;i<=l;i++)
for(int j=1;j<=l;j++)
ans=min(f[n][i][j],ans);
printf("%d",ans);
return 0;
}