NYOJ564 最优对称路径(记忆化搜索+spfa)
2016-04-11 21:13
288 查看
题意:
给你一个nxn的方格,从1,1开始走,每个点都会有一个权值 ,求到nxn的最短路径次数 (题目要求在对角线之间的路径是对称的)。
思路:
由于是对称的,所以可以把另外半个图直接累加在左上半个图,那么我只要求到对角线的最短路径的次数。
我们可以先利用spfa求出最短路径,然后根据最短的值,从终点开始记忆化搜索,利用之前spfa求得的剪枝。
给你一个nxn的方格,从1,1开始走,每个点都会有一个权值 ,求到nxn的最短路径次数 (题目要求在对角线之间的路径是对称的)。
思路:
由于是对称的,所以可以把另外半个图直接累加在左上半个图,那么我只要求到对角线的最短路径的次数。
我们可以先利用spfa求出最短路径,然后根据最短的值,从终点开始记忆化搜索,利用之前spfa求得的剪枝。
</pre><p><pre name="code" class="cpp">#include<stdio.h> #include<iostream> #include<algorithm> #include<queue> #include<math.h> #include<string.h> #include<vector> using namespace std; const int maxn = 210; typedef long long LL; const LL INF = 1e15; const LL mod = 1e9+9; int n; int mov[4][2]= {{1,0},{0,1},{-1,0},{0,-1}}; LL map[maxn][maxn]; bool vis[maxn][maxn]; LL cnt[maxn][maxn]; LL dist[maxn][maxn]; void spfa() { memset(vis,false,sizeof(vis)); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { dist[i][j]=INF; } } vis[1][1]=true; dist[1][1]=map[1][1]; pair <int,int> u,v; queue<pair<int,int> > q; u.first=1; u.second=1; q.push(u); memset(cnt,0,sizeof(cnt)); while (!q.empty()) { u=q.front(); q.pop(); vis[u.first][u.second]=false; for(int i=0; i<4; i++) { v.first=u.first+mov[i][0]; v.second=u.second+mov[i][1]; if(v.first<1||v.first>n||v.second<1||v.second>n) continue; if(v.first+v.second>n+1) continue; if(dist[v.first][v.second]>dist[u.first][u.second]+map[v.first][v.second]) { dist[v.first][v.second]=dist[u.first][u.second]+map[v.first][v.second]; if(!vis[v.first][v.second]) { vis[v.first][v.second]=true; q.push(v); } } } } } LL dp[maxn][maxn]; LL dfs(int x,int y) { int fx,fy; if(dp[x][y]) { return dp[x][y]; } for(int i=0; i<4; i++) { fx=x+mov[i][0]; fy=y+mov[i][1]; if(fx<1||fx>n||fy<1||fy>n) continue; if(fx+fy>n+1) continue; if(dist[fx][fy]+map[x][y]==dist[x][y]) { dp[x][y]+=(dfs(fx,fy)%mod); dp[x][y]%=mod; } } return (dp[x][y]%mod); } LL solve() { for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if(i+j>=n+1) continue; map[i][j]+=map[n-j+1][n-i+1]; } } spfa(); memset(dp,0,sizeof(dp)); LL minn=INF; for(int i=1; i<=n; i++) minn=min(minn,dist[i][n+1-i]); LL ans=0; dp[1][1]=1; for(int i=1; i<=n; i++) { if(dist[i][n+1-i]==minn) { ans+=dfs(i,n+1-i); ans%=mod; } } return ans; } int main() { while(scanf("%d",&n)&&n) { for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) scanf("%lld",&map[i][j]); printf("%lld\n",solve()); } return 0; }
相关文章推荐
- 2016-04-11/获取系统当前时间
- 用vector进行图的邻接表存储
- linux基础学习之 nfs挂载
- Hibernate管理Session
- 重学STM32---(九) ——CAN通信(一)
- 谷歌对面试者提出的15个让人疯狂的问题
- js练习题三:使div变色 密码提示框
- 联合巨头做庄开源,英特尔在云计算时代再造DIY模式
- 设计模式基础——UML类图
- Apache CXF实现的RESTful形式的webservices
- 从设计心理学理解交互设计的原则
- 值班管理数据表设计
- AOP execution
- jQuery Validate(表单验证)例子
- 二级缓存
- Hadoop优化与调整
- 汇编语言(王爽) 第11章 标志寄存器
- 汇编语言(王爽) 第10章 call和ret
- (1)初识mysql binlog
- 怎样发布程序