题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1428
漫步校园
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Problem Description
LL最近沉迷于AC不能自拔,每天寝室、机房两点一线。由于长时间坐在电脑边,缺乏运动。他决定充分利用每次从寝室到机房的时间,在校园里散散步。整个HDU校园呈方形布局,可划分为n*n个小方格,代表各个区域。例如LL居住的18号宿舍位于校园的西北角,即方格(1,1)代表的地方,而机房所在的第三实验楼处于东南端的(n,n)。因有多条路线可以选择,LL希望每次的散步路线都不一样。另外,他考虑从A区域到B区域仅当存在一条从B到机房的路线比任何一条从A到机房的路线更近(否则可能永远都到不了机房了…)。现在他想知道的是,所有满足要求的路线一共有多少条。你能告诉他吗?
Input
每组测试数据的第一行为n(2=<n<=50),接下来的n行每行有n个数,代表经过每个区域所花的时间t(0<t<=50)(由于寝室与机房均在三楼,故起点与终点也得费时)。
Output
针对每组测试数据,输出总的路线数(小于2^63)。
Sample Input
3
1 2 3
1 2 3
1 2 3
3
1 1 1
1 1 1
1 1 1
Sample Output
1
6
Author
LL
解题思路:典型的记忆化搜索,先结合优先队列bfs记录每一个点到终点最短路线条数(完成记忆化),然后dfs搜索路线条数即可~~~
代码如下:
1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 using namespace std; 5 int map[55][55], n; 6 int mark[55][55]; 7 __int64 dp[55][55]; 8 int dir[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 }; 9 struct node { 10 int x, y, time; 11 friend bool operator < (node x1, node x2){ 12 //优先队列,时间小的先出队 13 return x1.time > x2.time; 14 } 15 }; 16 void bfs(){ 17 priority_queue<node>q; 18 node cur, next; 19 cur.x = n;//从(n,n)开始往前找,每次找最小时间到达(n,n) 20 cur.y = n; 21 cur.time = map[n][n]; 22 mark[n][n] = 1; 23 q.push(cur); 24 while (!q.empty()){ 25 cur = q.top(); 26 q.pop(); 27 for (int i = 0; i < 4; i++){ 28 next.x = cur.x + dir[i][0]; 29 next.y = cur.y + dir[i][1]; 30 if (next.x >= 1 && next.x <= n&&next.y >= 1 && next.y <= n&&!mark[next.x][next.y]){ 31 mark[next.x][next.y] = 1; 32 map[next.x][next.y] += cur.time;//在原数组记录每个点到终点的最短时间 33 next.time = map[next.x][next.y]; 34 q.push(next); 35 } 36 } 37 } 38 } 39 __int64 dfs(int x, int y){ 40 if (dp[x][y] > 0)return dp[x][y]; 41 for (int i = 0; i<4; i++){ 42 int v = x + dir[i][0]; 43 int u = y + dir[i][1]; 44 if (v >= 1 && v <= n&&u >= 1 && u <= n&&map[x][y]>map[v][u])//保证离终点原来越近 45 dp[x][y] += dfs(v, u); 46 } 47 return dp[x][y]; 48 } 49 int main(){ 50 int i, j; 51 while (scanf("%d", &n) != -1){ 52 memset(mark, 0, sizeof(mark)); 53 for (i = 1; i <= n; i++) 54 for (j = 1; j <= n; j++) 55 scanf("%d", &map[i][j]); 56 bfs(); 57 memset(dp, 0, sizeof(dp)); 58 dp[n][n] = 1; 59 printf("%I64d ", dfs(1, 1)); 60 } 61 return 0; 62 }