Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions problems/0203.移除链表元素.md
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,45 @@ public class Solution
}
}
```
### Ruby#

```ruby
# 定义链表节点
class ListNode
attr_accessor :val, :next
def initialize(val = 0, _next = nil)
@val = val
@next = _next
end
end

# 删除链表中值为 val 的节点
def remove_elements(head, val)
# 创建一个虚拟头节点,这样可以简化删除头节点的处理
# 虚拟头节点的值为 0,指向当前链表的头节点
dummy = ListNode.new(0)
dummy.next = head

# 初始化当前节点为虚拟头节点
current = dummy

# 遍历链表,直到当前节点的下一个节点为空
while current.next
# 如果当前节点的下一个节点的值等于 val
if current.next.val == val
# 跳过该节点,即将当前节点的 next 指向下一个节点的 next
current.next = current.next.next
else
# 否则继续遍历,当前节点向前移动
current = current.next
end
end

# 返回删除 val 后的新链表的头节点,虚拟头节点的 next 就是新的头节点
dummy.next
end

```

<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
Expand Down
163 changes: 163 additions & 0 deletions problems/kamacoder/0126.骑士的攻击astar.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,170 @@ for _ in range(n):

### C

```C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义一个结构体,表示棋盘上骑士的位置和相关的 A* 算法参数
typedef struct {
int x, y; // 骑士在棋盘上的坐标
int g; // 从起点到当前节点的实际消耗
int h; // 从当前节点到目标节点的估计消耗(启发式函数值)
int f; // 总的估计消耗(f = g + h)
} Knight;

#define MAX_HEAP_SIZE 2000000 // 假设优先队列的最大容量

// 定义一个优先队列,使用最小堆来实现 A* 算法中的 Open 列表
typedef struct {
Knight data[MAX_HEAP_SIZE];
int size;
} PriorityQueue;

// 初始化优先队列
void initQueue(PriorityQueue *pq) {
pq->size = 0;
}

// 将骑士节点插入优先队列
void push(PriorityQueue *pq, Knight k) {
if (pq->size >= MAX_HEAP_SIZE) {
// 堆已满,无法插入新节点
return;
}
int i = pq->size++;
pq->data[i] = k;
// 上滤操作,维护最小堆的性质,使得 f 值最小的节点在堆顶
while (i > 0) {
int parent = (i - 1) / 2;
if (pq->data[parent].f <= pq->data[i].f) {
break;
}
// 交换父节点和当前节点
Knight temp = pq->data[parent];
pq->data[parent] = pq->data[i];
pq->data[i] = temp;
i = parent;
}
}

// 从优先队列中弹出 f 值最小的骑士节点
Knight pop(PriorityQueue *pq) {
Knight min = pq->data[0];
pq->size--;
pq->data[0] = pq->data[pq->size];
// 下滤操作,维护最小堆的性质
int i = 0;
while (1) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int smallest = i;
if (left < pq->size && pq->data[left].f < pq->data[smallest].f) {
smallest = left;
}
if (right < pq->size && pq->data[right].f < pq->data[smallest].f) {
smallest = right;
}
if (smallest == i) {
break;
}
// 交换当前节点与最小子节点
Knight temp = pq->data[smallest];
pq->data[smallest] = pq->data[i];
pq->data[i] = temp;
i = smallest;
}
return min;
}

// 判断优先队列是否为空
int isEmpty(PriorityQueue *pq) {
return pq->size == 0;
}

// 启发式函数:计算从当前位置到目标位置的欧几里得距离的平方(避免开方,提高效率)
int heuristic(int x, int y, int goal_x, int goal_y) {
int dx = x - goal_x;
int dy = y - goal_y;
return dx * dx + dy * dy; // 欧几里得距离的平方
}

// 用于记录从起点到棋盘上每个位置的最小移动次数
int moves[1001][1001];

// 骑士在棋盘上的8个可能移动方向
int dir[8][2] = {
{-2, -1}, {-2, 1}, {-1, 2}, {1, 2},
{2, 1}, {2, -1}, {1, -2}, {-1, -2}
};

// 使用 A* 算法寻找从起点到目标点的最短路径
int astar(int start_x, int start_y, int goal_x, int goal_y) {
PriorityQueue pq;
initQueue(&pq);

// 初始化 moves 数组,-1 表示未访问过的位置
memset(moves, -1, sizeof(moves));
moves[start_x][start_y] = 0; // 起点位置的移动次数为 0

// 初始化起始节点
Knight start;
start.x = start_x;
start.y = start_y;
start.g = 0;
start.h = heuristic(start_x, start_y, goal_x, goal_y);
start.f = start.g + start.h; // 总的估计消耗

push(&pq, start); // 将起始节点加入优先队列

while (!isEmpty(&pq)) {
Knight current = pop(&pq); // 取出 f 值最小的节点

// 如果已经到达目标位置,返回所需的最小移动次数
if (current.x == goal_x && current.y == goal_y) {
return moves[current.x][current.y];
}

// 遍历当前节点的所有可能移动方向
for (int i = 0; i < 8; i++) {
int nx = current.x + dir[i][0];
int ny = current.y + dir[i][1];

// 检查新位置是否在棋盘范围内且未被访问过
if (nx >= 1 && nx <= 1000 && ny >= 1 && ny <= 1000 && moves[nx][ny] == -1) {
moves[nx][ny] = moves[current.x][current.y] + 1; // 更新移动次数

// 创建新节点,表示骑士移动到的新位置
Knight neighbor;
neighbor.x = nx;
neighbor.y = ny;
neighbor.g = current.g + 5; // 每次移动的消耗为 5(骑士移动的距离平方)
neighbor.h = heuristic(nx, ny, goal_x, goal_y);
neighbor.f = neighbor.g + neighbor.h;

push(&pq, neighbor); // 将新节点加入优先队列
}
}
}

return -1; // 如果无法到达目标位置,返回 -1
}

int main() {
int n;
scanf("%d", &n);
while (n--) {
int a1, a2, b1, b2; // 起点和目标点的坐标
scanf("%d %d %d %d", &a1, &a2, &b1, &b2);

int result = astar(a1, a2, b1, b2); // 使用 A* 算法计算最短路径
printf("%d\n", result); // 输出最小移动次数
}
return 0;
}

```



Expand Down