标签:
2 1 1 1 1 3 1 1 1 1 1 1 2 1 1 0
2 3
原题链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=564
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1106
此题和HDU1428 漫步校园那题差不多,那题链接:http://blog.csdn.net/hurmishine/article/details/51913536
但是此题要求路径要关于副对角线对称,难点在此。
考虑到对称性,我们可将矩阵右下方部分“加到”左上方,求出从左上角到对角线的最短路径,再统计条便可。
具体看代码。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int INF=0x3f3f3f3f; const int MOD=1000000009; const int maxn=205; struct node { int x,y; }; int a[maxn][maxn]; int dis[maxn][maxn]; bool vis[maxn][maxn]; int dp[maxn][maxn]; int dir[4][2]= {1,0,0,1,-1,0,0,-1}; int n,minn; bool OK(int x,int y) { if(x<0||y<0||x+y>n-1)//越界或到右下部分 return false; return true; } void spfa() { memset(dis,INF,sizeof(dis)); memset(vis,false,sizeof(vis)); minn=INF; queue<node>q; node now ,next; q.push((node){0,0});//新技能get dis[0][0]=a[0][0]; while(!q.empty()) { now=q.front(); q.pop(); vis[now.x][now.y]=false; if(now.x+now.y==n-1) { if(dis[now.x][now.y]<minn) minn=dis[now.x][now.y]; continue; } for(int i=0;i<4;i++) { int xx=now.x+dir[i][0]; int yy=now.y+dir[i][1]; if(OK(xx,yy)&&dis[xx][yy]>dis[now.x][now.y]+a[xx][yy]) { dis[xx][yy]=dis[now.x][now.y]+a[xx][yy]; if(!vis[xx][yy]) { vis[xx][yy]=true; q.push((node){xx,yy}); } } } } } int DFS(int x,int y) { if(dp[x][y]!=-1) return dp[x][y]; if(x+y==n-1) return dp[x][y]=dis[x][y]==minn; dp[x][y]=0; for(int i=0;i<4;i++) { int xx=x+dir[i][0]; int yy=y+dir[i][1]; if(OK(xx,yy)&&dis[x][y]+a[xx][yy]==dis[xx][yy]) { dp[x][y]=(dp[x][y]+DFS(xx,yy)%MOD); } } return dp[x][y]; } int main() { //freopen("data/1016.txt","r",stdin); while(cin>>n,n) { for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { cin>>a[i][j]; if(i+j>=n) a[n-j-1][n-i-1]+=a[i][j]; } } spfa(); memset(dp,-1,sizeof(dp)); DFS(0,0); cout<<dp[0][0]<<endl; } return 0; }
NYOJ564 & CSU 1106 最优对称路径【记忆化搜索+最短路】
标签:
原文地址:http://blog.csdn.net/hurmishine/article/details/52241959