路径数
题目描述:
Euphemia 到一个 N*N 的药草田里采药,她从左上角的格子田(第一行,第
一列)出发,要到达右下角(第 N 行,第 N 列)的格子田,每次她可以走到与
当前格子有边相邻的格子去,但她不会走已经走过的格子,而且出于对美的要求,
她走过的路径是关于 左下-右上 对角线对称的。由于地势不同,在每个格子田
采药都会有一个疲劳度 Tij,Euphemia 想知道:有多少条合法路径,可以使得她
采药的疲劳度最小。
输入格式:
多组数据。
每组数据第一行一个整数 N,接下来 N 行,每行 N 个非零数字(1,2,3...9 中
一个),表示格子田的疲劳度。
当 N=0,输入结束。
输出格式:
对于每组数据,输出一个整数表示答案,答案%1000000009。
样例输入:
2
1
1
3
1
1
2
0
1
1
1 1
1 1
1 1
样例输出:
2
3数据范围与限制:
对于 20%的数据满足 N<=5。
对于另外 20%的数据满足 N<=40。
对于 100%的数据满足 N<=100,不超过 50 组数据。
首先我们可以把线的两边对折,这样就变成了半个矩阵,同时问题就转化成了从左上角到折线的位置的最短路径的条数有多少。
然后,我们可以用SPFA求单源最短路,这样起点到每个点的最短路就都有了。之后为了能够算出路径的条数,我们可以从起点开始,每次取队中d[]的值最小的点出队,然后按最短路径的走向向周围的点拓展,并将拓展成功的点入队。
最后,统计折线上的最短路的最小值,并把所有符合要求的路径的条数相加即可
其实SPFA和拓展求出路径条数的过程可以在一个SPFA内完成
有一个坑点就是如果一个点不在对角线且未在队列就说明:
1.这个点的未走过
2.这个点已出队,意味着对于它旁边的点,他已经加上了该点原来的路径数
如果不清零,接下来的过程会再算一遍,产生重复
意思就是如果(x+y<n+1&&vis[x][y]==0) 路径数[x][y]=0
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 typedef long long lol; 8 struct Node 9 { 10 int x,y; 11 }; 12 lol Mod=1000000009; 13 const int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1}; 14 lol dist[201][201],d[101][101],as,ans; 15 int n,a[201][201]; 16 bool vis[101][101]; 17 void SPFA() 18 {int i; 19 queue<Node>Q; 20 memset(dist,127/3,sizeof(dist)); 21 memset(vis,0,sizeof(vis)); 22 memset(d,0,sizeof(d)); 23 dist[1][1]=0; 24 d[1][1]=1; 25 Q.push((Node){1,1}); 26 while (Q.empty()==0) 27 { 28 Node u=Q.front(); 29 Q.pop(); 30 vis[u.x][u.y]=0; 31 if (u.x+u.y==n+1) continue; 32 for (i=1;i<=4;i++) 33 { 34 int x=u.x+dx[i],y=u.y+dy[i]; 35 if (x&&y&&x<=n&&y<=n&&y<=n-x+1&&dist[x][y]>=dist[u.x][u.y]+a[u.x][u.y]+a[n-u.y+1][n-u.x+1]) 36 { 37 if (dist[x][y]>dist[u.x][u.y]+a[u.x][u.y]+a[n-u.y+1][n-u.x+1]) 38 { 39 dist[x][y]=dist[u.x][u.y]+a[u.x][u.y]+a[n-u.y+1][n-u.x+1]; 40 d[x][y]=d[u.x][u.y]%Mod; 41 if (x+y<n+1&&vis[x][y]==0) 42 { 43 Q.push((Node){x,y}); 44 vis[x][y]=1; 45 } 46 } 47 else 48 if (dist[x][y]==dist[u.x][u.y]+a[u.x][u.y]+a[n-u.y+1][n-u.x+1]) 49 { 50 if(vis[x][y]==0&&x+y<n+1)d[x][y]=0; 51 d[x][y]+=d[u.x][u.y]; 52 d[x][y]%=Mod; 53 if (x+y<n+1&&vis[x][y]==0) 54 { 55 Q.push((Node){x,y}); 56 vis[x][y]=1; 57 } 58 } 59 } 60 } 61 } 62 } 63 int main() 64 {int i,j; 65 while (cin>>n&&n) 66 { 67 for (i=1;i<=n;i++) 68 { 69 for (j=1;j<=n;j++) 70 { 71 scanf("%d",&a[i][j]); 72 } 73 } 74 SPFA(); 75 as=2e9;ans=0; 76 for (i=1;i<=n;i++) 77 as=min(as,dist[i][n-i+1]+a[i][n-i+1]); 78 for (i=1;i<=n;i++) 79 if (as==dist[i][n-i+1]+a[i][n-i+1]) 80 ans+=d[i][n-i+1],ans%=Mod; 81 82 cout<<ans<<endl; 83 } 84 }