LeetCode_单周赛_343

6341. 保龄球游戏的获胜者

疯狂wa,被恶心坏了。
第 i 个是 xi,得分分为两种情况:

  1. 前两轮中击中 10 个瓶子的,价值 = 2 * xi
  2. xi
    需要注意的是,前两轮中任意一轮击中数量是 10,都可以翻倍。
    如果是第二轮,前面只有一轮,如果击中了 10 个,也是满足情况的。
    注意判断下标是否 ≥ 0

模拟

class Solution {
    public int isWinner(int[] a, int[] b) {
        int x = 0, y = 0, n = a.length;
        for (int i = 0; i < n; i++) {
            if ((i - 1 >= 0) && a[i - 1] == 10 || ((i - 2 >= 0) && a[i - 2] == 10)) x += 2 * a[i];
            else x += a[i];

            if ((i - 1 >= 0) && b[i - 1] == 10 || ((i - 2 >= 0) && b[i - 2] == 10)) y += 2 * b[i];
            else y += b[i];
        }
        if (x > y) return 1;
        else if (x < y) return 2;
        return 0;
    }
}

6342. 找出叠涂元素

先预处理出来每个数在 数组mat中的下标,便于遍历 arr 时使用。
每次遍历点,都将该点所在的行、列 +1,判断是否达到标准。
注意:列的统计和要和 行数n比较。行的统计和要和 列数m比较

预处理+统计行列涂色数

class Solution {
    private int n, m;
    private int[] row, col;
    private int[][] a;

    public int firstCompleteIndex(int[] arr, int[][] mat) {
        n = mat.length;
        m = mat[0].length;

        row = new int[n + 5];
        col = new int[m + 5];
        a = new int[m * n + 10][2];
        // 数字对应下标
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                a[mat[i][j]][0] = i;
                a[mat[i][j]][1] = j;
            }
        }

        for (int i = 0; i < m * n; i++) {
            int t = arr[i];
            row[a[t][0]]++;
            col[a[t][1]]++;

            if (row[a[t][0]] == m || col[a[t][1]] == n) return i;
        }
        return 0;
    }
}

6343. 前往目标的最小代价

把起点、终点、特殊路径的点都看作是图上的点。
dis[i] :start 到 i 的最短距离。初始时,dis[start] = 0,其余为 INF。
首先,从start出发,更新邻接的所有点的最短路:

  1. 更新到终点的距离,只能直接到终点,为曼哈顿距离(题目中的那个)
  2. 更新到所有特殊路径的终点的距离:直接走曼哈顿,或者先走到特殊路径起点,走特殊路径到其终点,取最小值。

然后每次都先找 dis 最小的点,先判断是不是终点,是的话就直接return,否则用它来更新其他特殊路径的终点。
已经确定是最短的,就放入vis中,不再遍历了。

关于为什么不管特殊路径的起点,我是这么想的:最终答案有可能是start直接走到target,曼哈顿距离。
如果没有特殊路径改变距离,中间经历其他点都是没用的,不会缩小距离的。
所以想减小距离,只能去尝试有没有小的特殊路径,并且特殊路径一定要走到它的终点才能利用它的cost。
所以就不用管特殊路径的起点,只看花费为cost的终点。

dijkstra

class Solution {
    // 普通路径是双向的,但是特殊路径是单向的
    private int N = (int) 1e5 + 10, INF = 0x3f3f3f3f;
    private HashMap<Long, Integer> dis = new HashMap<>(); // dis with start
    private HashSet<Long> vis = new HashSet<>(); // isVisited ?

    public int minimumCost(int[] start, int[] target, int[][] specialRoads) {
        long t = (long) target[0] << 32 | target[1]; // 终点,二维变一维
        dis.put(t, INF); // end
        dis.put((long) start[0] << 32 | start[1], 0); // start

        while (true) {
            long v = -1; // min dis's point
            for (var e : dis.entrySet())
                if (!vis.contains(e.getKey()) && (v == -1 || e.getValue() < dis.get(v)))
                    v = e.getKey(); // get min point

            if (v == t) return dis.get(t); // find end

            vis.add(v);

            int vx = (int) (v >> 32), vy = (int) (v & Integer.MAX_VALUE); // get v's position

            // update v to end
            dis.merge(t, dis.get(v) + Math.abs(target[0] - vx) + Math.abs(target[1] - vy), Math::min);
            // update v to special Point
            for (var r : specialRoads) {
                int x = r[2], y = r[3];
                int d = dis.get(v) + Math.min(Math.abs(vx - x) + Math.abs(y - vy),
                        Math.abs(vx - r[0]) + Math.abs(vy - r[1]) + r[4]);

                long w = (long) x << 32 | y;
                if (d < dis.getOrDefault(w, INF))
                    dis.put(w, d);
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值