您的位置:首页 > 理论基础

CSU1106 最优对称路径 湖南省第七届大学生计算机程序设计竞赛

2016-08-21 19:59 399 查看


最优对称路径

时间限制:1000 ms  |  内存限制:65535 KB
难度:3

描述
    给一个 n 行 n 列的网格,每个格子里有一个 1 到 9 的数字。你需要从左上角走到右下角,其中每一步只能往上、下、左、右四个方向之一走到相邻格子,不能斜着走,也不能走出网格,但可以重复经过一个格子。为了美观,你经过的路径还必须关于“左下-右上”这条对角线对称。下图是一个 6x6 网格上的对称路径。
 


    你的任务是统计所有合法路径中,数字之和最小的路径有多少条。

输入输入最多包含 25 组测试数据。每组数据第一行为一个整数 n(2<=n<=200)。以下 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


来源湖南省第七届大学生计算机程序设计竞赛
上传者
rihkddd
题目链接
http://acm.nyist.net/JudgeOnline/problem.php?pid=564

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1106

看完题目感觉很难做不了 后面发现跟杭电  http://blog.csdn.net/xky140610205/article/details/52269006 一样
就是多加个对称线 预处理下 就OK了 把图对折一次 对应的点加在一起
每次收到对称线就ok了

#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
using namespace std;
#define mod 1000000009
#define inf 0x3f3f3f3f
int n;
struct node
{
int x,y;
int step;
friend bool operator<(node a,node b)
{
return a.step>b.step;
}
} ft,et;
int dir[4][2]= {1,0,0,1,-1,0,0,-1};
int ap[210][210];
int dp[210][210];
int dis[210][210];
int vis[210][210];
int MIN;
int pd(int x,int y)
{
if(x<1||y<1||x+y>n+1)
return 1;
return 0;
}

void bfs()
{
MIN=inf;
memset(vis,0,sizeof(vis));
priority_queue<node>q;
ft.x=1;
ft.y=1;
ft.step=ap[1][1];
vis[1][1]=1;
dis[1][1]=ap[1][1]; // 找了半天没初始化
q.push(ft);
while(!q.empty())
{
ft=q.top();
q.pop();
if(ft.x+ft.y==n+1)
{
if(MIN>ft.step)
MIN=ft.step;
continue;
}
for(int i=0; i<4; i++)
{
et.x=ft.x+dir[i][0];
et.y=ft.y+dir[i][1];
if(vis[et.x][et.y]==1) continue;
if(pd(et.x,et.y)) continue;
dis[et.x][et.y]=ft.step+ap[et.x][et.y];
et.step=dis[et.x][et.y];
vis[et.x][et.y]=1;
q.push(et);
}
}

}

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]==MIN;
dp[x][y]=0;
for(int i=0; i<4; i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(pd(xx,yy)) continue;
if(dis[x][y]+ap[xx][yy]==dis[xx][yy])
dp[x][y]=(dp[x][y]+dfs(xx,yy))%mod;
}
return dp[x][y];
}

int main()
{
while(~scanf("%d",&n),n)
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&ap[i][j]);
for(int i=1; i<n; i++)
for(int j=1; j<=n-i; j++)
ap[i][j]+=ap[n+1-j][n+1-i];
bfs();
memset(dp,-1,sizeof(dp));
printf("%d\n",dfs(1,1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  NYOJ acm 算法
相关文章推荐