f[l][r][i][j]表示把l到r的机器人合并,停在(i,j)点的最小步数
f[l][r][i][j]=min{f[l][k][i][j]+f[k+1][r][i][j]}
f[l][r][i][j]=min{f[l][r][i'][j']+1}
记忆化搜索一下每个点从每个方向出发会走到哪里
注意,题目里可能出现环,要特判
spfa要加上一个优化才能通过
先把初始队列中的点按距离排序,每次扩展的点放在新队列里,取新队列和初始队列队尾较小的点进行扩展
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 510
#define inf 1000000000
using namespace std;
struct yts
{
int x,y,dis;
}q1[510*510],q2[510*510];
bool cmp(yts x,yts y) {return x.dis<y.dis;}
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
int d[4][maxn][maxn];
char s[maxn][maxn];
int dp[10][10][maxn][maxn];
bool vis[maxn][maxn],tag[4][maxn][maxn];
int n,w,h;
//0上1左2下3右
int cal(int x,int y) {return (x-1)*w+y;}
int dfs(int k,int x,int y)
{
if (x<1 || x>h || y<1 || y>w) return 0;
if (s[x][y]=='x') return 0;
if (d[k][x][y]) return d[k][x][y];
if (tag[k][x][y]) return -1;
tag[k][x][y]=1;
int _k=k;
if (s[x][y]=='A') _k=(k+1)%4;
if (s[x][y]=='C') _k=(k+3)%4;
d[k][x][y]=dfs(_k,x+dx[_k],y+dy[_k]);
if (!d[k][x][y]) d[k][x][y]=cal(x,y);
tag[k][x][y]=0;
return d[k][x][y];
}
int main()
{
scanf("%d%d%d",&n,&w,&h);
for (int i=1;i<=h;i++) scanf("%s",s[i]+1);
for (int i=1;i<=h;i++)
for (int j=1;j<=w;j++)
for (int k=0;k<4;k++)
d[k][i][j]=dfs(k,i,j);
for (int l=1;l<=n;l++)
for (int r=1;r<=n;r++)
for (int x=1;x<=h;x++)
for (int y=1;y<=w;y++)
dp[l][r][x][y]=inf;
for (int x=1;x<=h;x++)
for (int y=1;y<=w;y++)
if (s[x][y]-'0'>=1 && s[x][y]-'0'<=n) dp[s[x][y]-'0'][s[x][y]-'0'][x][y]=0;
for (int l=n;l>=1;l--)
for (int r=l;r<=n;r++)
{
for (int x=1;x<=h;x++)
for (int y=1;y<=w;y++)
for (int k=l;k<r;k++)
dp[l][r][x][y]=min(dp[l][r][x][y],dp[l][k][x][y]+dp[k+1][r][x][y]);
memset(vis,0,sizeof(vis));
int L=0,R=0;
int l1=0,r1=0;
for (int x=1;x<=h;x++)
for (int y=1;y<=w;y++)
if (dp[l][r][x][y]!=inf) q1[++R]=(yts){x,y,dp[l][r][x][y]},vis[x][y]=1;
sort(q1+1,q1+R+1,cmp);
while (L!=R || l1!=r1)
{
int x,y;
if (L==R || (l1!=r1 && dp[l][r][q1[L].x][q1[L].y]>dp[l][r][q2[l1].x][q2[l1].y]))
{
l1++;if (l1==500*500) l1=0;
x=q2[l1].x;y=q2[l1].y;
}
else
{
L++;if (L==500*500) L=0;
x=q1[L].x;y=q1[L].y;
}
for (int k=0;k<4;k++)
{
int xx=(d[k][x][y]-1)/w+1,yy=(d[k][x][y]-1)%w+1;
if (dp[l][r][xx][yy]>dp[l][r][x][y]+1)
{
dp[l][r][xx][yy]=dp[l][r][x][y]+1;
if (!vis[xx][yy])
{
r1++;if (r1==500*500) r1=0;
q2[r1]=(yts){xx,yy,dp[l][r][xx][yy]};
}
}
}
vis[x][y]=0;
}
}
int ans=inf;
for (int x=1;x<=h;x++)
for (int y=1;y<=w;y++)
ans=min(ans,dp[1][n][x][y]);
if (ans==inf) puts("-1"); else printf("%d\n",ans);
return 0;
}