试题分析
我们发现$dp(t,s1,s2,s3)$表示在$t$时刻$3$个人的位置。发现时间复杂度为$O(n \times L^3)$。不仅会$T$还会$MLE$,所以需要优化$dp$。我们发现当次$dp$合法时,肯定会有一项是到达的那个位置,所以可以优化掉一维。只需要把那个必须要经过的位置去掉,时间复杂度就变为$O(n \times L^2)$。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<climits> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int N=1001; const int L=201; int dp[N][L][L],val[L][L],n,l,p[N],minn=INT_MAX; bool judge(int x1,int x2,int x3){ return (x1!=x2)&&(x2!=x3)&&(x1!=x3); } int _min(int a,int b){ return a>b?b:a;} int main(){ l=read();n=read(); for(int i=1;i<=l;i++) for(int j=1;j<=l;j++) val[i][j]=read(); memset(dp,127/3,sizeof(dp));dp[0][1][2]=0,dp[0][2][1]=0;p[0]=3; for(int t=1;t<=n;t++){ p[t]=read(); for(int i=1;i<=l;i++){ for(int j=1;j<=l;j++){ /*val[i][p]*/ if(judge(p[t],p[t-1],j)){ dp[t][p[t-1]][j]=_min(dp[t][p[t-1]][j],dp[t-1][i][j]+val[i][p[t]]); dp[t][j][p[t-1]]=_min(dp[t][p[t-1]][j],dp[t][j][p[t-1]]); } /*val[j][p]*/ if(judge(p[t-1],i,p[t])){ dp[t][p[t-1]][i]=_min(dp[t][p[t-1]][i],dp[t-1][i][j]+val[j][p[t]]); dp[t][i][p[t-1]]=_min(dp[t][p[t-1]][i],dp[t][i][p[t-1]]); } /*val[p[t-1]][p]*/ if(judge(i,j,p[t])){ dp[t][i][j]=_min(dp[t][i][j],dp[t-1][i][j]+val[p[t-1]][p[t]]); dp[t][j][i]=_min(dp[t][j][i],dp[t][i][j]); } } } } for(int i=1;i<=l;i++) for(int j=1;j<=l;j++) { if(!(i!=j&&i!=p[n]&&j!=p[n])) continue; minn=min(minn,dp[n][i][j]); } printf("%d",minn); }