首先从终点bfs,保存每一个节点到终点的最短路径,然后从起点dfs,记忆化,如果满足题目给定的拓扑序就加上从那个点到终点的路径数。所谓满足拓扑序就是题目所给定的taking a path from A to B to be progress if there exists a route from B to his home that is shorter than any possible route from A,这句话仔细读上几十遍就能明白题目意图了。
漫步校园
代码:
#include <iostream>
#include <queue>
using namespace std;


int dir[4][2] =
{
{0, 1},
{0, -1},
{1, 0},
{-1, 0}};

struct point
{
int x;
int y;
int time;


bool friend operator < (point a, point b)
{
return a.time > b.time;
}

}temp, tt;

priority_queue < point > q;
int hash[51][51], map[51][51];
__int64 dp[51][51];
int n;


__int64 dfs(int x, int y)
{
int i;
int tx, ty;
__int64 sum = 0;

if(x == n && y == n)
return 1;


for(i = 0; i < 4; i++)
{
tx = x + dir[i][0];
ty = y + dir[i][1];
if(tx < 1 || ty < 1 || tx > n || ty > n)
continue;

if(hash[x][y] > hash[tx][ty])
{

if(dp[tx][ty] == -1)
{
dp[tx][ty] = dfs(tx, ty);
}
sum += dp[tx][ty];
}
}

return sum;
}

int main()
{
int i, j;

while(scanf("%d", &n) != EOF)
{


for(i = 1; i <= n; i++)
{

for(j = 1; j <= n; j++)
{
scanf("%d", &map[i][j]);
}
}
temp.x = n;
temp.y = n;
temp.time = map[n][n];
memset(hash, -1, sizeof(hash));
hash[n][n] = map[n][n];
while(!q.empty())
q.pop();

q.push( temp );


while(!q.empty())
{
temp = q.top();
q.pop();

for(i = 0; i < 4; i++)
{
tt.x = temp.x + dir[i][0];
tt.y = temp.y + dir[i][1];
if(tt.x < 1 || tt.y < 1 || tt.x > n || tt.y > n)
continue;
tt.time = temp.time + map[tt.x][tt.y];

if(hash[ tt.x ][ tt.y ] == -1 || tt.time < hash[ tt.x ][ tt.y ])
{
hash[ tt.x ][ tt.y ] = tt.time;
q.push( tt );
}
}
}

memset(dp, -1, sizeof(dp));

dp[1][1] = dfs(1, 1);
printf("%I64d\n", dp[1][1]);
}
return 0;
}