6341. 保龄球游戏的获胜者
疯狂wa,被恶心坏了。
第 i 个是 xi,得分分为两种情况:
- 前两轮中击中 10 个瓶子的,价值 = 2 * xi
- 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出发,更新邻接的所有点的最短路:
- 更新到终点的距离,只能直接到终点,为曼哈顿距离(题目中的那个)
- 更新到所有特殊路径的终点的距离:直接走曼哈顿,或者先走到特殊路径起点,走特殊路径到其终点,取最小值。
然后每次都先找 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);
}
}
}
}
文章评论