bfs,放缩
hdoj 1428 漫步校园
先放缩,求出没点离终点的最短距离。然后从起点bfs求出总的路径数,或者记忆化搜索求路径数。
#include <iostream> #include <queue> using namespace std; typedef __int64 lld; struct Node { int x, y; Node() {} Node(int a, int b) { x = a; y = b; } }; struct Node2 { int x, y; lld v; }; bool operator<( Node2 n1, Node2 n2 ) { return n1.v < n2.v; } lld inf = (1<<30) - 1; int n; lld num[55][55], minDis[55][55], ans[55][55]; int dir[4][2] = {1, 0, 0, 1, 0, -1, -1, 0 }; void input() { for( int i=0; i<n; ++i ) { for( int j=0; j<n; ++j ) { scanf( "%I64d", &num[i][j] ); } } } bool isBond( Node q ) { if( q.x < 0 || q.y < 0 || q.x >= n || q.y >= n ) return 1; return 0; } //放缩,求出每点到终点的最短距离 void getEveryDis() { queue<Node> Q; Node p, q; bool mark[55][55]; int i, j; for( i=0; i<n; ++i ) { for( j=0; j<n; ++j ) { minDis[i][j] = inf; mark[i][j] = 0; } } minDis[n-1][n-1] = num[n-1][n-1]; p.x = p.y = n-1; Q.push( p ); mark[p.x][p.y] = 1; while( !Q.empty() ) { p = Q.front(); Q.pop(); mark[p.x][p.y] = 0; for( i=0; i<4; ++i ) { q.x = p.x + dir[i][0]; q.y = p.y + dir[i][1]; if( isBond(q) ) continue; if( minDis[q.x][q.y] > minDis[p.x][p.y] + num[q.x][q.y]) { minDis[q.x][q.y] = minDis[p.x][p.y] + num[q.x][q.y]; if( !mark[q.x][q.y] ) { Q.push( q ); mark[q.x][q.y] = 1; } } } } } //记忆化搜索求路径数 lld dfs( Node p ) { int i; lld cnt = 0; Node q; if( p.x == n-1 && p.y == n-1 ) return 1; if( ans[p.x][p.y] != 0 ) return ans[p.x][p.y]; for( i=0; i<4; ++i ) { q.x = p.x + dir[i][0]; q.y = p.y + dir[i][1]; if( isBond( q ) ) continue; if( minDis[q.x][q.y] >= minDis[p.x][p.y]) continue; cnt += dfs( q ); } ans[p.x][p.y] = cnt; return cnt; } /* //bfs求出结果 void solve() { int i, j; Node2 p, q; bool mark[55][55]; priority_queue<Node2> Q; memset( ans, 0, sizeof(ans) ); memset( mark, 0, sizeof(mark) ); ans[0][0] = 1; p.x = p.y = 0; p.v = minDis[p.x][p.y]; mark[p.x][p.y] = 1; Q.push( p ); while( !Q.empty() ){ p = Q.top(); Q.pop(); if( ans[p.x][p.y] > p.v ) p.v = ans[p.x][p.y]; for( i=0; i<4; ++i ) { q.x = p.x + dir[i][0]; q.y = p.y + dir[i][1]; if( q.x < 0 || q.y < 0 || q.x >=n || q.y >= n )continue; if( minDis[q.x][q.y] >= minDis[p.x][p.y] ) continue; ans[q.x][q.y] += ans[p.x][p.y]; q.v = minDis[q.x][q.y]; if( !mark[q.x][q.y] ) { Q.push( q ); mark[q.x][q.y] = 1; } } } printf( "%I64d\n", ans[n-1][n-1] ); } */ int main() { // freopen( "c:/aaa.txt", "r", stdin) ; while( scanf( "%d", &n ) == 1 ) { input(); getEveryDis(); //solve(); memset( ans, 0, sizeof(ans) ); printf( "%I64d\n", dfs(Node(0, 0)) ); } return 0; }
.