最优对称路径
来源:互联网 发布:php 修改文件名 编辑:程序博客网 时间:2024/05/29 08:00
G - 最优对称路径
Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%I64d & %I64uDescription
给一个n行n列的网格,每个格子里有一个1到9的数字。你需要从左上角走到右下角,其中每一步只能往上、下、左、右四个方向之一走到相邻格子,不能斜着走,也不能走出网格,但可以重复经过一个格子。为了美观,你经过的路径还必须关于“左下-右上”这条对角线对称。下图是一个6x6网格上的对称路径。
你的任务是统计所有合法路径中,数字之和最小的路径有多少条。
你的任务是统计所有合法路径中,数字之和最小的路径有多少条。
Input
输入最多包含25组测试数据。每组数据第一行为一个整数n(2<=n<=100)。以下n行每行包含n个1到9的数字,表示输入网格。输入结束标志为n=0。
Output
对于每组数据,输出合法路径中,数字之和最小的路径条数除以1,000,000,009的余数。
Sample Input
2 1 1 1 1 3 1 1 1 1 1 1 2 1 1 0
Sample Output
2 3
Hint
无
思路:先把图压缩成左上角的一半 在用dij求出(0,0)点到左下-右上的斜边的各个点的最短路,然后只要斜边上的点满足最短路,就dfs深搜路径到(0.0)点,并用一个vis1标记当前坐标是否搜索过,如果搜索过直接返回该值,就是记忆化搜索,并且搜索的条件是当前的点加上当前点的权值要等于刚才走过来那个点的最短路的值才往下搜,因为要保证最短路,
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <queue>#include <algorithm>typedef __int64 LL;using namespace std;LL mod = 1000000009;const int maxn = 222222222;int vis[210][210],head[210][210],n,cnt,d[210][210],map[210][210];struct Edge{ int u[2],v[2],w; int next; Edge(int a =0,int b = 0,int e= 0,int r = 0,int c = 0) { u[0] = a; u[1] = b; w = c;v[0] = e;v[1] = r; }}e[450000];void add(Edge q){ e[cnt].u[0] = q.u[0]; e[cnt].u[1] = q.u[1]; e[cnt].v[0] = q.v[0]; e[cnt].v[1] = q.v[1]; e[cnt].w = q.w; e[cnt].next = head[q.u[0]][q.u[1]]; head[q.u[0]][q.u[1]] = cnt++;}struct node{ int x, y, val; friend bool operator <(node a, node b) { return a.val > b.val; } node (int a=0, int b=0, int c=0) { x = a; y = b;val = c; }};void dij(){ memset(vis,0,sizeof(vis)); int i,j; for(i = 0; i<n;i++) { for(j = 0; j<n;j++) { d[i][j] = maxn; } } d[0][0] = map[0][0]; priority_queue <node> q; q.push(node (0,0,d[0][0])); while (!q.empty()) { node w = q.top(); q.pop(); if(vis[w.x][w.y] == 1) { continue; } vis[w.x][w.y] = 1; for(i = head[w.x][w.y];i!=-1;i=e[i].next) { int end1 = e[i].v[0]; int end2 = e[i].v[1]; if(d[end1][end2] > d[w.x][w.y] + e[i].w) { d[end1][end2] = d[w.x][w.y] + e[i].w; q.push(node (end1,end2,d[end1][end2])); } } }}int ans1,aa[4] = {1,-1,0,0},bb[4]={0,0,1,-1},vis1[210][210];LL ans,dp[210][210];LL dfs(int x, int y){ if(x == 0&&y ==0) return 1; if(vis1[x][y] == 1) return dp[x][y]; vis1[x][y] = 1; int i; dp[x][y] = 0; for(i = 0; i < 4; i++) { int x1 = x + aa[i]; int y1 = y + bb[i]; if(x1>=0&&x1<n&&y1>=0&&y1<n-x1&&(d[x1][y1]+map[x][y] == d[x][y])) { dp[x][y] =( dp[x][y]%mod + dfs(x1,y1)%mod)%mod; } } return dp[x][y];}int main(){ int i,j,k; while (scanf("%d",&n)&&n) { for(i = 0; i<n;i++) { for(j = 0; j < n; j++) { scanf("%d",&map[i][j]); } } for(i = 0; i<n;i++) { for(j = 0; j < n - i; j++) { if(j!=n-i-1) map[i][j] += map[n-j-1][n-i-1]; } } memset(head,-1,sizeof(head)); cnt = 0; for(i = 0; i<n;i++) { for(j = 0; j < n-i; j++) { for(k = 0; k < 4; k++) { if(i+aa[k]>=0&&i+aa[k]<n&&j+bb[k]>=0&&j+bb[k]<n-i-aa[k]) { add(Edge(i,j,i+aa[k],j+bb[k],map[i+aa[k]][j+bb[k]])); } } } } dij(); ans1 = maxn; ans = 0; for(i = 0; i<n;i++) { if(d[i][n-i-1] < ans1) ans1 = d[i][n-i-1]; } memset(vis1,0,sizeof(vis1)); dp[0][0] = 1; for(i = 0; i < n; i++) { if(d[i][n-1-i] == ans1) ans=(ans%mod+dfs(i,n-1-i)%mod)%mod; } cout<<ans<<endl; } return 0;}
0 0
- 最优对称路径
- 最优对称路径
- 最优对称路径
- 最优对称路径
- 最优对称路径 CSU
- csu 1106 最优对称路径(最短路+路径数)
- 湖南省第七届程序设计竞赛 最优对称路径
- csu 1106 最优对称路径 最短路+记忆化搜索.
- NYOJ564 最优对称路径(记忆化搜索+spfa)
- csu 1106 最优对称路径(最短路+记忆化搜索)
- 湖南省第七届省赛 G - 最优对称路径(spfa+dp)
- 1106: 最优对称路径(最短路+记忆化搜索)
- NYOJ564 & CSU 1106 最优对称路径【记忆化搜索+最短路】
- CSU1106 最优对称路径 湖南省第七届大学生计算机程序设计竞赛
- C的最优路径
- 矩阵最优路径
- 迷宫求解最优路径
- mod4最优路径问题
- JNI问题:findLibrary returned null
- 帕那索斯博士的奇幻秀
- 450C - Jzzhu and Chocolate
- 安装Zookeeper
- JS 继承
- 最优对称路径
- man adduser
- kk音标导读(上):赖世雄老师26个英语字母导读示范 (附我备注)
- 小叮当与海盗仙子
- 单恋的那段时光
- 学习博客
- [c#]分析器错误消息: 发现不明确的匹配。
- 激乐人心.内嵌中字
- line-height绝对值和相对值的区别