#include<bits/stdc++.h> // 包含所有常用标准库,竞赛常用
using namespace std; // 使用std命名空间,避免重复写std::
#define int long long // 将int类型重定义为long long,防止数值溢出
const int N=12; // 地图最大尺寸(12x12)
const int MOD=1e4+10; // 状态中余数的最大模数(适配p-1的范围)
// 全局变量定义
int n,m,p,mod; // n:地图行数 m:地图列数 p:目标模数 mod:p-1(费马小定理相关)
int a[N][N]; // 存储地图每个位置的数值(路径累加用)
int b[N][N]; // 读取但未使用的第二个矩阵(可能是题目预留参数)
int c[N][N]; // 未使用的临时矩阵
int yu; // 未使用的余数临时变量
// dp[x][y][k]: 表示从起点到(x,y)位置,路径数值和模mod等于k时的最小步数
// 初始值-1表示该状态不可达
int dp[N][N][MOD];
// 方向数组:上下左右四个移动方向(下、右、上、左)
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
// BFS队列中的节点结构体
struct Node{
int x,y; // 当前位置的坐标(x,y)
int counter_part; // 从起点到当前位置的路径数值和 模mod 的结果
};
// 广度优先搜索(BFS)函数:从起点(sx,sy)到终点(ex,ey)寻找满足条件的最短路径
// 核心逻辑:记录每个位置+余数状态的最短步数
void bfs(int sx,int sy,int ex,int ey){
// 初始化dp数组为-1,表示所有状态初始不可达
memset(dp,-1,sizeof(dp));
queue<Node> q; // BFS队列,存储待扩展的节点
// 起点初始化:将起点(1,1)入队,初始余数为a[1][1]%mod,步数为0
q.push({sx,sy,a[sx][sy]%mod});
dp[sx][sy][a[sx][sy]%mod]=0;
// BFS主循环:队列不为空时持续扩展
while(!q.empty()){
Node front=q.front();q.pop(); // 取出队首节点并弹出
// 当前节点的步数(从起点到该节点的最短步数)
int dis=dp[front.x][front.y][front.counter_part];
// 遍历四个移动方向
for(int i=0;i<4;i++){
// 计算移动后的新坐标
int tx=front.x+dx[i];
int ty=front.y+dy[i];
// 边界检查:新坐标在地图范围内(1-based索引)
if(tx>=1&&tx<=n&&ty>=1&&ty<=m){
// 计算新余数:当前余数 + 新位置数值 后模mod
int counter_part=(front.counter_part+a[tx][ty])%mod;
// 如果该状态(tx,ty,counter_part)未被访问过
if(dp[tx][ty][counter_part]==-1){
dp[tx][ty][counter_part]=dis+1; // 步数+1
q.push({tx,ty,counter_part}); // 新状态入队
}
}
}
}
}
// 核心解题函数:处理问题逻辑,调用BFS并输出结果
void solve(){
mod=p-1; // 根据数论知识(费马小定理),将模数转为p-1
// 特判p=1的情况:任何数模1都是0,但题目要求可能无解,直接输出-1
if(p==1){
cout<<-1<<endl;
}else{
// 调用BFS,从(1,1)到(n,m)搜索最短路径
bfs(1,1,n,m);
// 检查终点(n,m)余数为0的状态是否可达
if(dp[n][m][0]==-1){
cout<<-1<<endl; // 不可达输出-1
}else{
// 可达则输出最短步数
cout<<dp[n][m][0]<<endl;
}
}
return;
}
// 主函数:程序入口
signed main(){
// 加速cin/cout输入输出,避免超时(竞赛常用)
ios::sync_with_stdio(false);
cin.tie(0);
// 输入地图尺寸n,m和目标模数p
cin>>n>>m>>p;
// 输入第一个矩阵a[N][N](路径数值矩阵)
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
// 输入第二个矩阵b[N][N](代码中未使用,可能是题目备用参数)
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>b[i][j];
}
}
// 调用解题函数
solve();
return 0;
}
总结