(类似)斯坦纳树+DP
\(f[l][r][i][j]\) 表示已经构成 \([l,r]\) 的机器人,并在点 \((i,j)\) 的最小代价。
预处理出 \(d[i][j][k]\) 表示在点 \((i,j)\) 方向为 \(k\) 时最终能够到达的点。
\(f[l][r][i][j]=\min(f[l][k][i][j],f[k+1][r][i][j])\)
\(枚举k,f[l][r][X][Y]=\min(f[l][r][X][Y],f[l][r][i][j]+1),(X,Y)表示(i,j,k)最终到达的点\)
spfa 要优化:用两个队列,一个存初始状态(先排完序再扔进去),一个存扩展出来的状态,每次取两个队头中较小的去扩展。
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<cstring> #define R register int using namespace std; namespace Luitaryi { inline int g() { R x=0,f=1; register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f; do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f; } const int N=10,M=510,Inf=0x3f3f3f3f; const int dx[]={-1,0,1,0},dy[]={0,-1,0,1}; struct node { int x,y,dis; inline bool operator < (const node& that) const {return dis<that.dis;} }; int n,h,w,ans=Inf; int d[M][M][4],f[N][N][M][M]; char s[M][M]; bool vis[M][M][4],inq[M][M]; #define P(i,j) ((i-1)*w+j) inline int dfs(int i,int j,int k) { if(i<1||i>h||j<1||j>w) return 0; if(s[i][j]=='x') return 0; if(d[i][j][k]) return d[i][j][k]; if(vis[i][j][k]) return -1; vis[i][j][k]=true; R K=k; if(s[i][j]=='A') K=(k+1)%4; if(s[i][j]=='C') K=(k+3)%4; d[i][j][k]=dfs(i+dx[K],j+dy[K],K); if(!d[i][j][k]) d[i][j][k]=P(i,j); vis[i][j][k]=false; return d[i][j][k]; } queue<node> q1,q2; vector<node> mem; inline void main() { n=g(),w=g(),h=g(); for(R i=1;i<=h;++i) scanf("%s",s[i]+1); for(R i=1;i<=h;++i) for(R j=1;j<=w;++j) for(R k=0;k<4;++k) d[i][j][k]=dfs(i,j,k); memset(f,0x3f,sizeof f); for(R i=1;i<=h;++i) for(R j=1;j<=w;++j) if(isdigit(s[i][j])) f[s[i][j]-'0'][s[i][j]-'0'][i][j]=0; for(R l=n;l>=1;--l) for(R r=l;r<=n;++r) { for(R i=1;i<=h;++i) for(R j=1;j<=w;++j) for(R k=l;k<r;++k) f[l][r][i][j]=min(f[l][r][i][j],f[l][k][i][j]+f[k+1][r][i][j]); for(R i=1;i<=h;++i) for(R j=1;j<=w;++j) if(f[l][r][i][j]!=Inf) mem.push_back((node){i,j,f[l][r][i][j]}),inq[i][j]=true; sort(mem.begin(),mem.end()); for(const auto& v:mem) q1.push(v); mem.clear(); while(q1.size()||q2.size()) { R x,y; if(q1.size()) { if(q2.size()) { if(f[l][r][q1.front().x][q1.front().y]<f[l][r][q2.front().x][q2.front().y]) x=q1.front().x,y=q1.front().y,q1.pop(); else x=q2.front().x,y=q2.front().y,q2.pop(); } else x=q1.front().x,y=q1.front().y,q1.pop(); } else x=q2.front().x,y=q2.front().y,q2.pop(); inq[x][y]=false; for(R k=0;k<4;++k) { R xx=(d[x][y][k]-1)/w+1,yy=(d[x][y][k]-1)%w+1; if(f[l][r][xx][yy]>f[l][r][x][y]+1) { f[l][r][xx][yy]=f[l][r][x][y]+1; if(!inq[xx][yy]) { q2.push((node){xx,yy,f[l][r][xx][yy]}); inq[xx][yy]=true; } } } } } for(R i=1;i<=h;++i) for(R j=1;j<=w;++j) ans=min(ans,f[1][n][i][j]); if(ans==Inf) puts("-1"); else printf("%d\n",ans); } } signed main() {Luitaryi::main(); return 0;}
2020.01.18
来源:https://www.cnblogs.com/Jackpei/p/12209865.html