[CCPC 2024 重庆站] 骰子 的题解


记住只在没有思路时使用题解,不要从它复制粘贴代码。请尊重题目和题解的作者。
在解题之前提交题解的代码会导致封禁。

作者: admin

概述

本题要求在 n \times m 网格上通过滚动骰子并选择性记录底面数字,最大化所有记录数字的总和。核心解法是利用构造性证明,当 n,m \ge 2 时,可使骰子经过每个格子时底面均为 6,因此答案为 6 \times n \times m。

分析
核心观察

只要存在一种滚动路径,使得骰子访问每个格子时底面数字都是 6,就能让所有格子都写下最大值 6。由于每次可以在经过格子时选择不写数字,只需关注如何通过滚动控制底面为 6。

思路

构造一个局部操作:在 2 \times 2 的方块中,从左上角开始,经过“下、右、上”三次滚动后,骰子到达右上角,并且底面恢复为 6。具体地,设当前位置 (i,j) 已经写下 6,执行:

  1. 向前(向下)滚到 (i+1,j),此时 6 转到后面;
  2. 向右滚到 (i+1,j+1),6 仍在后面;
  3. 向后(向上)滚到 (i,j+1),6 转到下面。 这样就在 (i,j+1) 写下了 6。利用这个操作,可以借助下一行逐列向右推进,直到当前行的最后一列。

当到达行末 (i,m) 时,使用对称操作将骰子转到下一行并使 6 落在 (i+1,m):

  1. 向左滚到 (i,m-1),6 转到右面;
  2. 向前(向下)滚到 (i+1,m-1),6 仍在右面;
  3. 向右滚到 (i+1,m),6 转到下面。 这样就在 (i+1,m) 写下了 6。之后在下一行再反向(向左)推进,同样可逐格写下 6。

对于最后一行(i=n),可以借助上一行完成类似操作,只需将“向下”改为“向上”即可。由于网格尺寸至少为 2 \times 2,上述构造始终有效,能覆盖所有格子。

具体示例

以 2 \times 2 网格为例:

  • 初始在 (1,1),底面为 6,写下 6。
  • 向下滚到 (2,1),不写数字;向右滚到 (2,2),不写数字;向上滚到 (1,2),底面为 6,写下 6。
  • 再从 (1,2) 利用向下、向左、向上(需借助下一行)到达 (2,2),写下 6。 最终四个格子均为 6,总和 24。
算法步骤
  1. 读取网格尺寸 n 和 m。
  2. 根据构造性证明,最大总和为所有格子都写下 6,即 6 \times n \times m,直接输出该整数。
复杂度分析
  • 时间:O(1)
  • 空间:O(1)
实现注意事项
  • 输入保证 2 \le n,m \le 1000,n \times m 最大为 10^6,6 \times n \times m 约为 6 \times 10^6,在 int 范围内。
  • 直接输出计算结果,无需模拟骰子滚动。
  • 注意使用 long long 并非必须,但为了代码健壮性也可使用。
源代码
#include <iostream>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    cout << 6 * n * m << endl;
    return 0;
}
n, m = map(int, input().split())
print(6 * n * m)

评论

目前没有评论。