IMA+(DeepSeek or 混元)撰写Noip2008提高组第三题传纸条题解

目录

一、提问词

二、IMA+混元

三、IMA+DeepSeek

 三、说明


使用同样的本地知识库,使用相同的提问词,在IMA环境中,选择混元和DeepSeek,会有什么样不同的体验呢?

一、提问词

请提供信息奥赛2008年提高组传纸条的题解,要求: 
1、从文件“message.in”读数据,答案写入文件“message.out”。 
2、不使用C++11以后版本的语法规则。 
3、解释题解中的主要算法。

二、IMA+混元

2008年信息奥赛提高组传纸条题解

【题目描述】

题目要求在一个二维网格中找到两条不交叉的路径,使得路径上的数字之和最大。路径从左上角 (1, 1) 出发,到达右下角 (m, n)。路径上的每个格子只能走一次。

【解题思路】

此问题可以通过动态规划来解决。我们定义一个四维数组 f[i][j][k][l] 表示从 (0, 0) 位置出发,通过两条不交叉的路径到达 (i, j)(k, l) 的最大数字之和。

【动态规划方程】

动态规划的转移方程为:

$$F[i][j][k][l] = \max \{ F[i-1][j][k-1][l], F[i-1][j][k][l-1], F[i][j+1][k-1][l], F[i][j+1][k][l-1] \} + G[i][j] + G[k][l]$$

其中,G[i][j] 是网格中 (i, j) 位置的数字。

【优化】

通过观察可以发现,纸条传的横坐标加纵坐标等于走的步数,即 l = i + j - k(当 l > 0)。利用这个关系可以将四维数组降维到三维数组,从而降低时间复杂度。

【实现代码】

#include<stdio.h>
#include<stdlib.h>

int f[52][52][52] = {0}, n, m;
int G[52][52];

int max(int a, int b, int c, int d) {
    if (a < b) a = b;
    if (a < c) a = c;
    if (a < d) a = d;
    return a;
}

int main() {
    freopen("message.in", "r", stdin);
    freopen("message.out", "w", stdout);
    scanf("%d%d", &m, &n);
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            scanf("%d", &G[i][j]);
        }
    }

    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            for (int k = 1; k <= m; k++) {
                int l = i + j - k;
                if (l > 0 && l <= n) {
                    f[i][j][k] = max(f[i-1][j][k-1], f[i-1][j][k], f[i][j-1][k-1], f[i][j-1][k]) + G[i][j] + G[k][l];
                    if (i == k && j == l) {
                        f[i][j][k] -= G[i][j]; // 避免重复计算
                    }
                }
            }
        }
    }

    printf("%d\n", f[m][n][m]);
    return 0;
}

【解释】

  1. 输入输出:程序从文件 message.in 读取数据,并将结果写入文件 message.out
  2. 初始化:使用一个三维数组 f 来存储动态规划的状态,初始值为0。
  3. 读取网格:读取网格的大小 mn,以及每个格子的数字。
  4. 动态规划:通过三层循环遍历所有可能的路径组合,计算并更新状态。
  5. 输出结果:最终输出 f[m][n][m],即从左上角到右下角的最大数字之和。

通过这种方式,我们可以有效地解决传纸条问题,并确保路径不交叉。

三、IMA+DeepSeek

根据提供的文档内容,以下是2008年信息奥赛提高组传纸条问题的题解:


【题解】

算法核心:多进程动态规划

核心思路:将问题转化为同时运行两个纸条从起点到终点的路径,定义 f[i][j][k][l] 为两个纸条分别到达 (i,j)(k,l) 时的最大价值和。通过优化步数关系 i + j = k + l(路径同步性质),将状态压缩为三维。

【实现代码(C语言)】

#include<stdio.h>
#include<stdlib.h>

int f[52][52][52][52] = {0}, G[52][52];

int max(int a, int b, int c, int d) {
    if (a < b) a = b;
    if (a < c) a = c;
    if (a < d) a = d;
    return a;
}

int main() {
    freopen("message.in", "r", stdin);
    freopen("message.out", "w", stdout);
    int m, n;
    scanf("%d%d", &m, &n);
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            scanf("%d", &G[i][j]);

    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            for (int k = 1; k <= m; k++) {
                int l = i + j - k;
                if (l < 1 || l > n) continue;

                f[i][j][k][l] = max(
                    f[i-1][j][k-1][l], 
                    f[i-1][j][k][l-1], 
                    f[i][j-1][k-1][l], 
                    f[i][j-1][k][l-1]
                ) + G[i][j] + G[k][l];

                if (i == k && j == l)
                    f[i][j][k][l] -= G[i][j]; // 去重
            }

    printf("%d\n", f[m][n][m][n]);
    return 0;
}

【代码说明】

  1. 输入输出
    使用 freopenmessage.in 读取输入,结果写入 message.out

  2. 动态规划状态定义
    四维数组 f[i][j][k][l] 表示两个纸条分别到达 (i,j)(k,l) 时的最大值。
    由于两条路径必须同步(每步移动距离相同),通过 l = i + j - k 消去第四维度,时间复杂度降至 $O(n^3)$。

  3. 状态转移
    当前状态的最优值由四种先前状态转移而来:

    • 纸条1向下,纸条2向下
    • 纸条1向下,纸条2向右
    • 纸条1向右,纸条2向下
    • 纸条1向右,纸条2向右
      转移后需加上当前格子的值 G[i][j]G[k][l]
  4. 路径去重
    若两纸条走到同一格子 (i,j)(k,l),需扣除重复计算的数字(f[i][j][k][l] -= G[i][j])。


【算法分析】

  • 时间复杂度:O(mn(m+n)),适配题目数据规模。
  • 空间复杂度:O(m^2 ╳ n^2),通过四维数组保存状态。实际因降维优化,循环后等效为三维操作。
  • 关键优化:利用步数同步性简化状态转移,避免暴力枚举所有四维情况。

 三、说明

1、DeepSeek模式有推理分析过程,由于不能复制,不方便截图,故未展示。

2、两段代码都通过了Cena评测。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liufangshun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值