1 条题解
-
0
题目题解
题目理解
我们需要判断是否存在一个 的非负整数网格,使得没有一条贪婪路径(即每一步都向右或向下移动到数值更大的相邻单元格的路径)能够达到所有向下/向右路径中的最大值。
关键观察
1. 平凡情况: 或
当网格只有一行或一列时,从左上角到右下角只有唯一一条路径。这条路径既是贪婪路径(因为没有其他选择),也是所有路径中的最大值路径。因此,不存在满足条件的网格,输出
"NO"。2. 特殊小网格:
在 网格中,从 到 只有两条路径:
- 右 → 下:
- 下 → 右:
第一步之后,贪婪规则会选择数值更大的相邻单元格:
- 如果 ,贪婪路径走右→下
- 如果 ,贪婪路径走下→右
- 如果相等,任选其一
不难验证,贪婪路径总会选择数值较大的那条路径,因此贪婪路径必定达到最大值。所以 网格也不存在满足条件的网格,输出
"NO"。3. 其他所有情况: 且
对于这些情况,存在构造使得贪婪路径无法达到最大值,输出
"YES"。构造方法
假设 (否则可以转置网格),构造一个 的网格如下:
- 首先将所有单元格初始化为 。
- 修改左上角的 子网格为:
[ \begin{bmatrix} 1 & 3 & 2 \ 1 & 3 & 1 \end{bmatrix} ]
即:
- ,,
- ,,
- 其余单元格保持为
验证构造的正确性
最大值路径
考虑路径:$(1,1) \rightarrow (2,1) \rightarrow (2,2) \rightarrow (2,3) \rightarrow \cdots \rightarrow (2,m) \rightarrow (3,m) \rightarrow \cdots \rightarrow (n,m)$
这条路径经过:
- :值
- 第 行所有单元格:从 到 全部为 (除了 和 ,但 和 也在其中)
- 然后向下走到
计算这条路径的和:
- 第一列:
- 第二行:包含 和 ,其余为 ,共 个单元格
- 加上右下角路径上的其他单元格
可以验证这条路径的和达到了理论最大值(因为我们在第二行收集了较大的 ,且其余位置全是 ,没有浪费)。
贪婪路径的局限
贪婪路径的第一步必须选择向右或向下中数值更大的邻居:
- 从 出发,比较 和 ,显然 ,所以贪婪路径第一步必须向右到 。
此时路径已经固定为: $(1,1) \rightarrow (1,2) \rightarrow (1,3) \rightarrow \cdots$
由于 很大,贪婪路径被迫沿着第一行向右移动,无法进入第二行去获取 (虽然两个 数值相等,但贪婪规则允许任选,但这里 已经很大,后续比较中可能不会转向)。
通过具体计算可以发现,这条贪婪路径的总和严格小于上面构造的最大值路径,从而证明了不存在贪婪路径能达到全局最大值。
时间复杂度
- 判断条件: 每个测试用例
- 总复杂度:,满足 的限制
代码实现
#include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t--) { int n, m; cin >> n >> m; // 只有一行或一列,或 2x2 网格时,所有贪婪路径都能达到最大值 if (n == 1 || m == 1 || (n == 2 && m == 2)) { cout << "NO\n"; } else { cout << "YES\n"; } } return 0; }总结
本题的关键在于识别出仅当网格为 、 或 时,贪婪路径才能保证达到全局最大值;其他情况下都可以通过巧妙构造使贪婪路径无法达到最优。这种构造利用了 子网格中数值的巧妙分布,迫使贪婪路径在第一步就做出"错误"的选择。
- 1
信息
- ID
- 6186
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者