传送门
看题之后一上手写了个dfs,结果发现tle了?
分析一下dfs的复杂度:如果不考虑最优化剪枝的话,是搜到终点再返回的。那么在最坏情况下,每个点的访问次数是指数级别的。
这不T就鬼了啊
改成spfa之后就A了。由于每一个点从四个方向走过来时的方案有可能是不同的,所以f(i,j,k)表示到(i,j)这个点,是从方向k走过来的最优值。也就相当于把一个点拆成了4个来做。
spfa的复杂度是 O(kE) 的,k一般为2或3,所以非常稳
dfs(tle)
#include
#include
#include
using namespace std;
#define N 105
#define inf 2000000000
int n,sx,sy,tx,ty,ans;
char a[N][N],s[N];
int f[N][N][5];
int dx[5]={0,0,0,1,-1};int dy[5]={0,1,-1,0,0};
void dfs(int x,int y,int dep,int dir)
{
if (dep>=f[x][y][dir]||dep>=ans) return;
f[x][y][dir]=dep;
if (x==tx&&y==ty)
{
ans=min(ans,dep);
return;
}
for (int i=1;i<=4;++i)
{
int nx=x+dx[i],ny=y+dy[i];
if (nx<1||nx>n||ny<1||ny>n||a[nx][ny]=='x') continue;
if (!dir||dir==i) dfs(nx,ny,dep,i);
else dfs(nx,ny,dep+1,i);
}
}
int main()
{
scanf("%d\n",&n);
for (int i=1;i<=n;++i)
{
gets(s);
for (int j=1;j<=n;++j)
{
a[i][j]=s[j-1];
if (s[j-1]=='A') sx=i,sy=j;
if (s[j-1]=='B') tx=i,ty=j;
}
}
ans=inf;
memset(f,127,sizeof(f));
f[sx][sy][1]=f[sx][sy][2]=f[sx][sy][3]=f[sx][sy][4]=0;
dfs(sx,sy,0,0);
printf("%d\n",ans);
}
spfa
#include
#include
#include
#include
using namespace std;
#define N 105
int n,sx,sy,tx,ty,ans;
char a[N][N],s[N];
int f[N][N][4];
bool vis[N][N][4];
int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};
struct hp{int x,y,dir;};
queue q;
int Min(int a,int b,int c,int d)
{
if (a>b) a=b;
if (a>c) a=c;
if (a>d) a=d;
return a;
}
int main()
{
scanf("%d\n",&n);
for (int i=1;i<=n;++i)
{
gets(s);
for (int j=1;j<=n;++j)
{
a[i][j]=s[j-1];
if (s[j-1]=='A') sx=i,sy=j;
if (s[j-1]=='B') tx=i,ty=j;
}
}
memset(f,127,sizeof(f));
f[sx][sy][0]=f[sx][sy][1]=f[sx][sy][2]=f[sx][sy][3]=0;
vis[sx][sy][0]=vis[sx][sy][1]=vis[sx][sy][2]=vis[sx][sy][3]=true;
q.push((hp){sx,sy,0});q.push((hp){sx,sy,1});q.push((hp){sx,sy,2});q.push((hp){sx,sy,3});
while (!q.empty())
{
hp now=q.front();q.pop();
vis[now.x][now.y][now.dir]=false;
for (int i=0;i<4;++i)
{
int x=now.x+dx[i],y=now.y+dy[i];
if (x<1||x>n||y<1||y>n||a[x][y]=='x') continue;
int len;
if (i==now.dir) len=0;
else len=1;
if (f[x][y][i]>f[now.x][now.y][now.dir]+len)
{
f[x][y][i]=f[now.x][now.y][now.dir]+len;
if (!vis[x][y][i]) vis[x][y][i]=true,q.push((hp){x,y,i});
}
}
}
ans=Min(f[tx][ty][0],f[tx][ty][1],f[tx][ty][2],f[tx][ty][3]);
printf("%d\n",ans);
}
①永远不要忘记分析时间复杂度。