他考虑从A区域到B区域仅当存在一条从B到机房的路线比任何一条从A到机房的路线更近(否则可能永远都到不了机房了…”
这句话一定要理解清楚。就是说,对于当前位置,如果下一个状态与终点的最短距离大于或者等于当前位置到终点的最短距离,那么这个下一个状态是不可取的!到此,就能明白,此题就是求出所有点与终点的最短距离,然后再从起点进行记忆化搜索。
#include "queue"
#include "iostream"
#include "algorithm"
using namespace std;
struct comp
{
int x,y,dis;
friend bool operator<(comp n1,comp n2)
{
return n2.dis<n1.dis;
}
};
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int inf=99999999;
__int64 dp[51][51];
int dis[51][51],a[51][51];
int n;
void bfs()
{
priority_queue<comp>q;
comp cur,next;
int i;
int hash[51][51];
cur.x=n;
cur.y=n;
cur.dis=a[n][n];
dis[n][n]=a[n][n];
q.push(cur);
memset(hash,0,sizeof(hash));
hash[n][n]=1;
while (!q.empty())
{
cur=q.top();
q.pop();
for (i=0;i<4;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if (next.x<1 || next.x>n || next.y<1 || next.y>n) continue;
if (hash[next.x][next.y]==1) continue;
next.dis=dis[next.x][next.y]=cur.dis+a[next.x][next.y];
hash[next.x][next.y]=1;
q.push(next);
}
}
}
__int64 dfs(int x,int y)
{
int i,xx,yy;
if (x==n && y==n ) return 1;
if (dp[x][y]!=0) return dp[x][y];
for (i=0;i<4;i++)
{
xx=x+dir[i][0];
yy=y+dir[i][1];
if (xx<1 || xx>n || yy<1 || yy>n) continue;
if (dis[xx][yy]<dis[x][y])
dp[x][y]+=dfs(xx,yy);
}
return dp[x][y];
}
int main()
{
int i,j;
while (scanf("%d",&n)!=EOF)
{
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
dis[i][j]=inf;
}
memset(dp,0,sizeof(dp));
bfs();
printf("%I64d\n",dfs(1,1));
}
return 0;
}