HDU 1428 漫步校园
最短路+DP
先预处理从(n,n)到每一格的最短路。
然后对每个点距离从大到小进行排序,然后就可以线性DP递推了。
#include<cstdio> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const int INF=0x7FFFFFFF; const int maxn=60; int n; int a[maxn][maxn],dis[maxn][maxn]; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; struct Node { int a,b; Node(int x,int y){a=x,b=y;} }; struct X { int x,y,dis; }s[maxn*maxn]; long long dp[maxn][maxn]; void BFS() { queue<Node>Q; dis[n][n]=a[n][n]; Node node(n,n); Q.push(node); while(!Q.empty()) { Node head=Q.front(); Q.pop(); for(int i=0;i<4;i++) { int x=head.a+dir[i][0]; int y=head.b+dir[i][1]; if(x>n||x<=0) continue; if(y>n||y<=0) continue; if(dis[head.a][head.b]+a[x][y]>=dis[x][y]) continue; dis[x][y]=dis[head.a][head.b]+a[x][y]; Q.push(Node(x,y)); } } } bool cmp(const X&a,const X&b) { return a.dis>b.dis; } int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); dis[i][j]=INF; } BFS(); int sz=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) s[sz].x=i,s[sz].y=j,s[sz].dis=dis[i][j],sz++; sort(s,s+sz,cmp); memset(dp,0,sizeof dp); dp[1][1]=1; for(int i=0;i<sz;i++) { for(int j=0;j<4;j++) { int x=s[i].x+dir[j][0]; int y=s[i].y+dir[j][1]; if(x>n||x<=0) continue; if(y>n||y<=0) continue; if(dis[s[i].x][s[i].y]<=dis[x][y]) continue; dp[x][y]=dp[x][y]+dp[s[i].x][s[i].y]; } } printf("%lld\n",dp[n][n]); } return 0; }