湖南省第七届大学生计算机程序设计竞赛 The Seventh Hunan Collegiate Programming Contest
题目G
最优对称路径
题目G
最优对称路径
给一个n行n列的网格,每个格子里有一个1到9的数字。你需要从左上角走到右下角,其中每一步只能往上、下、左、右四个方向之一走到相邻格子,不能斜着走,也不能走出网格,但可以重复经过一个格子。为了美观,你经过的路径还必须关于“左下-右上”这条对角线对称。下图是一个6x6网格上的对称路径。
你的任务是统计所有合法路径中,数字之和最小的路径有多少条。
输入
输入最多包含25组测试数据。每组数据第一行为一个整数n(2<=n<=100)。以下n行每行包含n个1到9的数字,表示输入网格。输入结束标志为n=0。
输出
对于每组数据,输出合法路径中,数字之和最小的路径条数除以1,000,000,009的余数。
样例输入
2
1 1
1 1
3
1 1 1
1 1 1
2 1 1
0
样例输出
2
3
可以按对角线折过来,然后最短路的求法,从(1,1)到对角线所有的点的最短路求出来,有点类似于SPFA,把每个更新过的点加入队列去做扩展,选出其中最小的路
然后从对角线上的点一个个选满足是最短的,然后从这些点中dfs找出所有的路线,这里对于找过的路要标记一下用来剪支
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#define inf 10000
#define maxn 1000000009
using namespace std;
int matrix[205][205];
int d[205][205];
queue<int> q;
int nx[]={1,0,0,-1};
int ny[]={0,-1,1,0};
int down[205][205];
int dp[205][205];
bool flag[205][205];
int n;
int check(int x,int y)
{
if(x>0&&y>0&&x<=n&&y<=n-x+1)
return 1;
return 0;
}
int dfs(int x,int y)
{
// printf("~~~%d %d\n",x,y);
if(flag[x][y])
return dp[x][y];
flag[x][y]=1;
for(int i=0;i<4;i++)
{
int ax=x+nx[i];
int ay=y+ny[i];
if(check(ax,ay)&&d[x][y]==matrix[x][y]+d[ax][ay])
dp[x][y]=(dp[x][y]%maxn+dfs(ax,ay)%maxn)%maxn;
}
return dp[x][y]%maxn;
}
int main()
{
while(scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&matrix[i][j]);
int sign=n;
memset(down,0,sizeof(down));
memset(dp,0,sizeof(dp));
memset(flag,0,sizeof(flag));
for(int i=1;i<=n;i++,sign--)
{
for(int j=1;j<sign;j++)
{
matrix[i][j]+=matrix[n-j+1][n-i+1];
}
}
sign=n;
for(int i=1;i<=n;i++,sign--)
{
for(int j=1;j<=sign;j++)
{
d[i][j]=inf;
}
}
q.push(1);
q.push(1);
d[1][1]=matrix[1][1];
while(!q.empty())
{
int dx=q.front();
q.pop();
int dy=q.front();
q.pop();
down[dx][dy]=0;
// printf("~~~%d %d\n",dx,dy);
for(int i=0;i<4;i++)
{
int mx=dx+nx[i];
int my=dy+ny[i];
if(check(mx,my)&&d[mx][my]>d[dx][dy]+matrix[mx][my])
{
// printf("!!%d %d\n",mx,my);
d[mx][my]=d[dx][dy]+matrix[mx][my];
if(down[mx][my]==0)
{
down[mx][my]=1;
q.push(mx);
q.push(my);
}
}
}
}//SPFA
int mins=10000;
for(int i=1,j=n;i<=n&&j>0;i++,j--)
if(d[i][j]<mins)
mins=d[i][j];
int path=0;
dp[1][1]=1;
for(int i=1,j=n;i<=n&&j>0;i++,j--)
if(d[i][j]==mins)
path=(path%maxn+dfs(i,j)%maxn)%maxn;
printf("%d\n",path);
}
}