【问题标题】:How to traverse an array and find all reachable points in C?如何遍历数组并找到C中的所有可到达点?
【发布时间】:2017-07-21 16:30:23
【问题描述】:

我一直在考虑如何从给定的起点 Arr[x][y] 找到数组中的所有可到达点,其中可到达点是与当前位置值相差不超过 2 的点.然后我想返回一个数组,它在所有可到达的位置都有 1,在无法到达的位置有 0。

假设 Arr[6][6] 看起来像这样:

10 11 14 18 20 20 
11 12 11 19 20 20 
24 28 12 15 18 31
44 46 13 12 57 30
42 45 10 14 59 31
38 42 46 16 16 23

那么返回的数组会是这样的

1 1 0 0 0 0 
1 1 1 0 0 0
0 0 1 0 0 0
0 0 1 1 0 0
0 0 0 1 0 0
0 0 0 1 1 0

我认为实现这一目标的最佳方法是创建一个 newArr 然后有 4 种不同的情况,我将当前位置与其每个邻居进行比较,然后如果它们可以到达,则设置 newArr[x][y ] 为 1。否则将其设置为 0。有人可以解释我如何确定下一步要移动到哪里,以及如何跟踪我已经测试过的点吗?

考虑原始数组中的[0][0]位置,比较后,既然可以右移或下移,我该如何决定呢?或者以某种方式两者兼而有之?

【问题讨论】:

  • 解决方案表示第2行第3列(从左下角第1行第1列开始)的50是可达的。这意味着对角连接计数——R3C4 中的 52 是值 50 的 2 内的唯一单元格。所以,你必须从所有方向看,看起来——从当前单元格最多 8 条路。但是,解决方案并不完全一致。 R1C5 处的 56 应该是解决方案的一部分,除非有一条未说明的规则关于“必须与当前单元格中的值不同,但在当前单元格中的值的 2 以内”。
  • @JonathanLeffler 抱歉,我在输入结果数组时犯了一个错误。我想我现在修好了,但不允许对角线移动

标签: c arrays algorithm multidimensional-array


【解决方案1】:

我认为你可以使用 DFS(深度优先搜索)来解决这个问题。我认为 BFS 也可以。 c代码:

#include <stdio.h>

int row,col,x,y;
int a[6][6]={
50,51 ,54, 58, 60, 60,
48, 52, 51, 59, 60, 60, 
44, 48, 52, 55, 58, 61,
44, 46, 53, 52, 57, 60,
42, 45, 50, 54, 59, 61,
38, 42, 46, 56, 56, 63
};// the date
int vis[6][6];// the result
int dir[4][2]={
    1,0,0,1,0,-1,-1,0
};
void dfs(int x,int y){
    for(int i=0;i<4;i++){  //4 direction
        int nx=x+dir[i][0];
        int ny=y+dir[i][1];
        if(!vis[nx][ny]&&abs(a[nx][ny]-a[x][y])<=2&&nx>=0&&ny>=0&&nx<6&&ny<6){
            vis[nx][ny]=1;
            dfs(nx,ny);
        }
    }
}
int main()
{
    vis[6][6]={0};
    scanf("%d%d",&x,&y);
    vis[x][y]=1;
    dfs(x,y);
    for(int i=0;i<6;i++){
        for(int j=0;j<6;j++){
            printf("%d",vis[i][j]);
        }
        printf("\n");
    }
    return 0;
}

【讨论】:

  • 欢迎来到 Stack Overflow。当问题标记为 C 时,请不要提供 C++ 解决方案。这两种语言有很大的不同,在 C 中合适的东西在 C++ 中通常是不合适的,而在 C++ 中合适的东西在 C 中通常(或至少经常)不可能。学习 C 的人往往没有技能将 C++ 翻译成 C 所必需的。
【解决方案2】:

你走在正确的道路上。是的,你需要检查邻居。您根据与所有 4 个邻居的比较(或更少,具体取决于位置)做出决定。

这是一个典型的 BFS 问题。看看herehere。你从一个点开始,然后到邻居那里做检查(这取决于你要解决的问题),然后更新结果矩阵并继续。

通常使用队列来实现 BFS。这是算法:

Set result [n][n] as all zero
Insert the beginning point (i,j) to a queue Q
result[i][j] = 1  // the starting point is reachable from itself
While queue is not empty:
  Take point (x,y) from Q 
     For each neighbor (z,w) of (x,y):  //which are north, south, east, west
       if (result[z][w] == 0 && | value[x][y] - value[z][w] | <= 2) {
          result[z][w] = 1
          push point(z,w) into Q
       }

[更新 1]:感谢 @Jonathan Leffler 的评论指出 8 个邻居,而不是 4 个,以及需要 @Shayna Grose 确认的 value[x][y] - value[z][w] != 0 可能的额外条件

[更新 2]:还原。根据@Shayna Grose 的评论:不允许对角线(需要考虑 4 个邻居)并且 diff = 0 是可以的。

【讨论】:

  • 请注意,原始解决方案矩阵中似乎存在“故障”(或一对故障);不允许使用对角线,并且需要对角线的解点是错误的(省略了一个不需要对角线的解点,另一个错误)。
  • 作为 n 函数的 this 的运行时间是多少? O(n^2)? @arash
  • @Newbie18 在最坏的情况下是的。因为我们需要访问每个位置(在最坏的情况下)并进行 4 次比较(除了有 2 或 3 次比较的边)。所以二次复杂度。
【解决方案3】:

您可能需要考虑类似flood fill 算法。您的“目标颜色”将是您的起点值,您的“替换颜色”将是目标 ±2 范围内的任何点。与其“绘制”数据数组,不如在返回数组中标记索引。 calloc 是初始清零返回数组的好选择。

在评估您的起点后,您将评估与该索引相邻的索引。如果您返回的数组中的索引已标记为 1,则可以忽略该索引,因为它已经被算法覆盖。

【讨论】:

  • 洪水填充也是我的第一个想法。
猜你喜欢
  • 2021-11-24
  • 1970-01-01
  • 2017-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多