我最近遇到了这个动态编程问题,我想看看是否有人对解决这个问题的方法有想法。我在这方面遇到了困难,这可能是因为我被困在了创建一棵大树来处理所有可能性的想法中。
问题
有一个字符可以在二维(x,y)坐标网格上移动.字符放置在点(0,0)。 从(x,y)字符可以移动到(x+1,y),(x-1,y),(x,y+1)和(x,y-1)。 有些地点是危险的,埋有地雷。为了知道哪些点是安全的,我们检查abs(x)和abs(y)的数字之和是否小于或等于23。 例如,点(64,-59)不安全,因为6+4+5+9= 24,大于23。点(105,-17)是安全的,因为1
字符可以访问的区域有多大?
发布于 2020-10-06 03:24:01
对于-1000, -1000 ... 1000, 1000
字段max有相同的假设,下面是用C#
编写的简单BFS版本
函数来检查点是否安全。
bool isSafe(int x, int y){
return (sum(Math.Abs(x)) + sum(Math.Abs(y))) < 24;
}
数字之和(假设非负输入)
int sum(int n){
int ret = 0;
while(n > 0){
ret += n%10;
n = n/10;
}
return ret;
}
BFS算法
var visited = new bool[2000, 2000];
var queue = new Queue<(int x, int y)>();
var steps = new List<(int di, int dj)>() {(-1, 0), (1, 0), (0, -1), (0, 1)};
int count = 1;
queue.Enqueue((0, 0));
visited[1000, 1000] = true;
while (queue.Count != 0)
{
var point = queue.Dequeue();
foreach (var step in steps)
if (!visited[point.x + step.di + 1000, point.y + step.dj + 1000] && isSafe(point.x + step.di, point.y + step.dj))
{
count++;
visited[point.x + step.di + 1000, point.y + step.dj + 1000] = true;
queue.Enqueue((point.x + step.di, point.y + step.dj));
}
}
Console.WriteLine(count);
输出
592597
在发现可达的单元格后,您可以看到图
发布于 2020-10-06 02:52:32
让我们编写一个简单的DFS。
首先,让我们考虑可以访问多少个单元,这样我们的算法就不会永远运行下去。在(999,999)的左上角和(-999,999)的右下角,你不能走得更远,因为正方形的一个坐标是±999,但是9+9+9> 23。在这个广场上有1999年*< 4M点,所以DFS会非常快。
#include <cmath>
#include <iostream>
const int SQUARE_SIDE = 1'000;
// v[i][j] is true if cell (i - SQUARE-SIDE, j - SQUARE_SIDE) was already
// visited during DFS, false otherwise.
bool v[2 * SQUARE_SIDE][2 * SQUARE_SIDE];
int answer = 0;
const struct {
int dx;
int dy;
} moves[] = {
{1, 0}, // Up
{-1, 0}, // Down
{0, -1}, // Left
{0, 1} // Right
};
int calc_abs_sum(int n) {
n = abs(n);
int sum = 0;
while (n) {
sum += n % 10;
n /= 10;
}
return sum;
}
void dfs(int x, int y) {
// Add SQUARE_SIDE to make indices non-negative.
v[x + SQUARE_SIDE][y + SQUARE_SIDE] = true;
answer++;
for (const auto &move : moves)
if (calc_abs_sum(x + move.dx) + calc_abs_sum(y + move.dy) <= 23 &&
!v[x + move.dx + SQUARE_SIDE][y + move.dy + SQUARE_SIDE]) {
dfs(x + move.dx, y + move.dy);
}
}
int main() {
dfs(0, 0);
std::cout << answer << std::endl;
}
我们就有592597了。
发布于 2020-10-14 00:51:04
我的回答太长了,所以我在HackerNoon的一篇文章中记录了一个Java解决方案,以及思考过程和对坐标系统的详细解释。
https://stackoverflow.com/questions/64218531
复制相似问题