这道题首先是用spfa算法求一下最短路,然后再搜索一下。
这里要用到记忆化搜索,记忆化搜索我刚学,理解得很肤浅,我是这么理解的。对于A->B->C->D这样的关系,判断哪些状态可以到达D状态。如果是一般的搜索,对于A,就是先判断A能否到达B,然后是C,然后是D,完成这些之后确定A可以到达D状态。对于B状态和C状态也是如此。
这样的搜索对于每一个子状态,我们需要多次计算。所谓记忆化搜索是在搜索中掺杂了动态规划的思想。依旧对于刚才的例子来说,我们在得到C状态可以到达D状态之后,对于B状态能不能到达D状态的判断,我们不需要再按照之前的方式,我们只需要判断B状态可以到达C状态,那么B状态就一定可以到达D状态,因为我们之前已经确定C状态可以到达D状态。对于A状态,我们只需要判断它能到达B状态,我们就可以确定它一定可以到达D状态。这样就减少了很多子问题的重复计算。
刚学的记忆化搜索,理解还非常肤浅,有什么不对的地方,欢迎指正。
发一份跟别人对拍着的代码:
原代码链接:点击打开链接
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 55
#define inf 0x3f3f3f3f
typedef long long LL;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int dis[N][N],map[N][N];
LL ans[N][N];
int n;
struct node
{
int x,y;
};
void bfs()
{
node cur,next;
queue<node>q;
cur.x=n;
cur.y=n;
dis[cur.x][cur.y]=map[n][n];
q.push(cur);
while(!q.empty())
{
cur=q.front();
q.pop();
for(int i=0;i<4;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(next.x>0&&next.x<=n&&next.y>0&&next.y<=n)
{
if(dis[cur.x][cur.y]+map[next.x][next.y]<dis[next.x][next.y])
{
q.push(next);
dis[next.x][next.y]=dis[cur.x][cur.y]+map[next.x][next.y];
}
}
}
}
return ;
}
LL dfs(int x,int y)
{
if(x==n&&y==n) return 1;
if(ans[x][y]>0) return ans[x][y];//ans[x][y]>0说明这个点已经计算过,不需要重新计算,直接返回结果就行。
for(int i=0;i<4;i++)
{
int xx,yy;
xx=x+dir[i][0];
yy=y+dir[i][1];
if(xx>0&&xx<=n&&y>0&&y<=n)
{
if(dis[x][y]>dis[xx][yy])
{
ans[x][y]+=dfs(xx,yy);
}
}
}
return ans[x][y];
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
dis[i][j]=inf;
}
}
memset(ans,0,sizeof(ans));
bfs();
dfs(1,1);
printf("%I64d\n",ans[1][1]);
}
return 0;
}