首页 > 试题广场 >

走一个大整数迷宫

[编程题]走一个大整数迷宫
  • 热度指数:723 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}给定一个 n \times m 的矩阵迷宫,其中第 i 行第 j 列的格子权值为

c_{i,j}=a_{i,j}\times p^{2^{b_{i,j}}}

\hspace{15pt}LH 起始位于 (1,1),出口位于 (n,m)。迷宫配有一个计数器,初始值为 c_{1,1}。在任意时刻,若计数器的值满足 \text{counter} \equiv 0 \pmod{(p-1)},且 LH 身处出口 (n,m),大门即刻打开,LH 得以逃离。

\hspace{15pt}每经过 1 秒,LH 必须向上、下、左、右四个方向中的某一方向移动一步(不得停留,也不得走出迷宫)。假设 LH 从 (i,j) 移动到 (i',j'),则计数器会累加 c_{i',j'}

\hspace{15pt}请计算 LH 最快需要多少秒才能逃离;若无论如何都无法逃离,则输出 -1

输入描述:
\hspace{15pt}输入共三部分:
\hspace{23pt}\bullet\,第一行输入三个整数 n,m,p\left(1\leqq n,m\leqq 10;\ 2\leqq p\leqq 10^{4}\right)
\hspace{23pt}\bullet\,接下来 n 行,每行 m 个整数,构成矩阵 a_{i,j}
\hspace{23pt}\bullet\,再接下来 n 行,每行 m 个整数,构成矩阵 b_{i,j},范围均为 0\leqq a_{i,j},b_{i,j}\leqq 10^{6}


输出描述:
\hspace{15pt}输出一个整数,代表最短逃离时间;若无法逃离,输出 -1
示例1

输入

3 3 10
1 2 3
0 1 4
0 0 0
1 0 0
0 0 1
0 1 0

输出

6

说明

C=\begin{bmatrix}<br /> 100 &20  &30 \\<br />  0& 10 & 400\\<br />  0& 0 &0<br />\end{bmatrix}

第一秒,从 (1,1) 走到 (1,2),计数器的值为 120

第二秒,从 (1,2) 走到 (1,3),计数器的值为 150

第三秒,从 (1,3) 走到 (1,2),计数器的值为 170

第四秒,从 (1,2) 走到 (2,2),计数器的值为 180

第五秒,从 (2,2) 走到 (3,2),计数器的值为 180

第六秒,从 (3,2) 走到 (3,3),计数器的值为 180,是 9 的倍数,逃出迷宫。

img
p1(modp1),所以ci,j=ai,j,b不需要处理
发表于 2025-08-21 04:29:43 回复(1)
这道题太变态了,没有AI的帮助我基本解不出
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>
//关键核心:只有找到更短时间的才继续
// 为什么这样设计:
// 因为对于路径搜索来说,重要的不是计数器的实际值,而是:

// 位置 (x, y)

// 计数器模(p-1)的值(因为最终条件是 counter % (p-1) == 0)

// 如果两个路径:

// 路径A:在时间t₁到达(x,y),counter_mod = k

// 路径B:在时间t₂到达(x,y),counter_mod = k

// 且 t₁ < t₂,那么路径A更优,我们只需要记录路径A。
typedef struct {
    int x;
    int y;
    int time;
    int counter;
} pos;

#define N 1000000
pos queue[N];
int queue_front = 0;
int queue_rear = 0;

void queue_push(pos temp) {
    if((queue_rear + 1) % N != queue_front) {
        queue[queue_rear] = temp;
        queue_rear = (queue_rear + 1) % N;
    }
}

bool is_empty_queue() {
    return queue_front == queue_rear;
}

pos queue_pop() {
    if(!is_empty_queue()) {
        pos temp = queue[queue_front];
        queue_front = (queue_front + 1) % N;
        return temp;
    }
    pos temp = {-1, -1, -1, -1};
    return temp;
}

int main() {
    int n, m, p;
    scanf("%d %d %d", &n, &m, &p);
    int a[n][m];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &a[i][j]);
        }
    }

    int b[n][m];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &b[i][j]);
        }
    }

    // 关键修改:使用最小时间数组代替visited
    int min_time[n][m][p];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            for (int k = 0; k < p; k++) {
                min_time[i][j][k] = INT_MAX;
            }
        }
    }

    pos start = {0, 0, 0, a[0][0]};
    int start_mod = a[0][0] % (p-1);
    queue_push(start);
    min_time[0][0][start_mod] = 0;

    int result = -1;
    
    while (!is_empty_queue()) {
        pos temp = queue_pop();
        
        // 如果当前时间大于已知最小时间,跳过
        if (temp.time > min_time[temp.x][temp.y][temp.counter % (p-1)]) {
            continue;
        }
        
        if (temp.x == n-1 && temp.y == m-1) {
            if (temp.counter % (p-1) == 0) {
                // 关键:找到解立即返回,因为BFS第一次找到的就是最短的
                printf("%d", temp.time);
                return 0;
            }
        }

        int dx[] = {-1, 1, 0, 0};
        int dy[] = {0, 0, -1, 1};
        
        for (int i = 0; i < 4; i++) {
            int nx = temp.x + dx[i];
            int ny = temp.y + dy[i];
            
            if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                int new_counter = temp.counter + a[nx][ny];
                int counter_mod = new_counter % (p-1);
                int new_time = temp.time + 1;
                
                // 只有找到更短时间才继续
                if (new_time < min_time[nx][ny][counter_mod]) {
                    min_time[nx][ny][counter_mod] = new_time;
                    pos t = {
                        .x = nx,
                        .y = ny,
                        .time = new_time,
                        .counter = new_counter
                    };
                    queue_push(t);
                }
            }
        }
    }

    printf("-1");
    return 0;
}


发表于 2025-10-21 16:28:00 回复(0)