You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

网格文字输入最短路径算法无法通过全部测试用例求助

问题根因定位

你的代码能跑通2*2的单测样例完全是巧合,核心bug集中在输入处理、逻辑鲁棒性两部分,逐个列:

  • 宽高读取顺序写反
    题目明确输入顺序是先给网格宽度、再给网格高度,你的代码变量定义是先赋值Height再读Width,只要测试用例宽高不相等,整个网格的行列维度直接错误,所有字符坐标计算全乱。你跑通的2*2样例因为宽高相等,刚好没暴露这个问题。
  • 待输入文本处理不符合要求
    题目规定网格内容之后的所有行都是待输入文本,不是单行,如果你只读取了第一行作为目标串,多行输入的内容会全部丢失;另外你没有过滤无效字符:待输入文本里所有不存在于网格的字符需要直接跳过,不能加入匹配序列,否则递归时找不到对应字符,直接返回错误结果。
  • 最小值判断逻辑有严重隐患
    你用FinalPath > NewPath ^ FinalPath == -1做最小值判断,属于典型的可读性极差的炫技式代码:C#中逻辑异或^的优先级低于比较运算符,虽然当前场景下计算结果歪打正着,但只要后续修改变量类型、调整判断条件,很容易出现非预期的逻辑结果。
  • 递归逻辑无剪枝+重复遍历网格效率极低
    每次递归都双层循环遍历整个网格找当前目标字符的位置,没有提前缓存字符到坐标列表的映射,而且DFS过程中没有剪枝:如果当前累计路径长度已经超过已经找到的最短路径,还会继续往下递归,遇到长文本、多重复字符的用例直接超时。
  • 额外注意:你贴的代码缩进混乱,大括号对齐有问题,如果实际运行的代码和贴出的缩进一致,会存在作用域错误,直接导致循环逻辑截断。
修复方案
  1. 先修正输入读取逻辑
    • 第一行输入转int赋值给Width,第二行输入转int赋值给Height
    • 读取第三行作为网格内容Content
    • 循环读取后续所有行,拼接成完整的待输入原始文本
    • 预处理原始文本:遍历每个字符,判断是否存在于网格内容中,只保留存在的字符,组成最终的匹配序列Words,如果过滤后Words长度为0,直接返回0即可
  2. 提前做字符坐标缓存,避免每次递归扫全表
    初始化一个字典Dictionary<char, List<(int x, int y)>> charPositions,遍历填充好的网格,把每个字符对应的所有坐标存到对应列表里,后续找目标字符的位置直接查字典就行,不用双层循环。
  3. 优化最短路径计算逻辑,替换有风险的判断
    把异或判断改成直白的if (FinalPath == -1 || NewPath < FinalPath),减少出错概率;递归时如果当前累计路径长度已经大于等于已找到的最短路径,直接return剪枝,不用继续往下递归。
    更推荐用动态规划替代纯DFS:每处理一个字符,只需要记录到达该字符每个出现位置的最短路径长度,处理下一个字符时,只需要遍历上一个字符所有位置到当前字符所有位置的曼哈顿距离,更新最短值即可,时间复杂度是O(n*k^2)(n是目标串长度,k是单个字符的最大重复次数),不会出现指数级超时的问题。
  4. 确认初始调用参数正确
    初始位置是网格左上角也就是坐标(0,0),第一次递归的参数是a=0(找第一个目标字符)、FirstX=0、FirstY=0、PathLength=0,不要传错初始坐标。
  5. 最终总操作数 = 最短移动路径长度 + 过滤后有效目标串的长度(每个字符一次确认点击)
修复后核心逻辑参考
// 预处理字符坐标缓存
Dictionary<char, List<(int x, int y)>> posMap = new Dictionary<char, List<(int x, int y)>>();
for (int i = 0; i < Height; i++)
{
    for (int j = 0; j < Width; j++)
    {
        char c = grid[i, j];
        if (!posMap.ContainsKey(c))
            posMap[c] = new List<(int x, int y)>();
        posMap[c].Add((i, j));
    }
}

// DP实现:dp[i][p]表示选第i个字符的第p个位置时的最短移动距离
List<int> prevDp = new List<int>();
// 初始化第一个字符的dp值
var firstPositions = posMap[Words[0]];
foreach (var (x,y) in firstPositions)
{
    prevDp.Add(Math.Abs(0 - x) + Math.Abs(0 - y));
}

for (int i = 1; i < Words.Length; i++)
{
    var currPositions = posMap[Words[i]];
    List<int> currDp = new List<int>(new int[currPositions.Count]);
    for (int currIdx = 0; currIdx < currPositions.Count; currIdx++)
    {
        var (cx, cy) = currPositions[currIdx];
        int minDist = int.MaxValue;
        for (int prevIdx = 0; prevIdx < prevDp.Count; prevIdx++)
        {
            var (px, py) = posMap[Words[i-1]][prevIdx];
            int dist = prevDp[prevIdx] + Math.Abs(cx - px) + Math.Abs(cy - py);
            if (dist < minDist)
                minDist = dist;
        }
        currDp[currIdx] = minDist;
    }
    prevDp = currDp;
}

int minMove = prevDp.Min();
int total = minMove + Words.Length; // 加确认点击次数

拿题目给的3*3样例跑这段逻辑,算出来minMove是8,加7次确认总结果15,和样例输出完全一致。

内容的提问来源于stack exchange,提问作者CodeAche

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 00:01:06