我需要编写一个程序来绘制给定矩阵中的所有可能路径,这些路径可以通过仅向左,向右和向上移动来获得。 一个人不应该多次越过同一个位置。另请注意,在特定路径上,我们可能会或可能不会在所有可能的方向上使用运动。
路径将从矩阵的左下角开始,并将到达右上角。 以下符号用于表示当前位置的运动方向:
+---+
| > | right
+---+
+---+
| ^ | up
+---+
+---+
| < | left
+---+
在最终位置使用符号*
来表示路径的结束。
示例:
对于5x8矩阵,使用向左,向右和向上的方向,下面显示了2个不同的路径。
路径1:
+---+---+---+---+---+---+---+---+
| | | | | | | | * |
+---+---+---+---+---+---+---+---+
| | | > | > | > | > | > | ^ |
+---+---+---+---+---+---+---+---+
| | | ^ | < | < | | | |
+---+---+---+---+---+---+---+---+
| | > | > | > | ^ | | | |
+---+---+---+---+---+---+---+---+
| > | ^ | | | | | | |
+---+---+---+---+---+---+---+---+
路径2
+---+---+---+---+---+---+---+---+
| | | | > | > | > | > | * |
+---+---+---+---+---+---+---+---+
| | | | ^ | < | < | | |
+---+---+---+---+---+---+---+---+
| | | | | | ^ | | |
+---+---+---+---+---+---+---+---+
| | | > | > | > | ^ | | |
+---+---+---+---+---+---+---+---+
| > | > | ^ | | | | | |
+---+---+---+---+---+---+---+---+
任何人都可以帮我吗?
我试图解决使用列表问题。我很快意识到我正在制造灾难。这是我试过的代码。
solution x y = travel (1,1) (x,y)
travelRight (x,y) = zip [1..x] [1,1..] ++ [(x,y)]
travelUp (x,y) = zip [1,1..] [1..y] ++ [(x,y)]
minPaths = [[(1,1),(2,1),(2,2)],[(1,1),(1,2),(2,2)]]
travel startpos (x,y) = rt (x,y) ++ up (x,y)
rt (x,y) | odd y = map (++[(x,y)]) (furtherRight (3,2) (x,2) minPaths)
| otherwise = furtherRight (3,2) (x,2) minPaths
up (x,y) | odd x = map (++[(x,y)]) (furtherUp (2,3) (2,y) minPaths)
| otherwise = furtherUp (2,3) (2,y) minPaths
furtherRight currpos endpos paths | currpos == endpos = (travelRight currpos) : map (++[currpos]) paths
| otherwise = furtherRight (nextRight currpos) endpos ((travelRight currpos) : (map (++[currpos]) paths))
nextRight (x,y) = (x+1,y)
furtherUp currpos endpos paths | currpos == endpos = (travelUp currpos) : map (++[currpos]) paths
| otherwise = furtherUp (nextUp currpos) endpos ((travelUp currpos) : (map(++[currpos]) paths))
nextUp (x,y) = (x,y+1)
identify lst = map (map iden) lst
iden (x,y) = (x,y,1)
arrows lst = map mydir lst
mydir (ele:[]) = "*"
mydir ((x1,y1):(x2,y2):lst) | x1==x2 = '>' : mydir ((x2,y2):lst)
| otherwise = '^' : mydir ((x2,y2):lst)
surroundBox lst = map (map createBox) lst
bar = "+ -+"
mid x = "| "++ [x] ++" |"
createBox chr = bar ++ "\n" ++ mid chr ++ "\n" ++ bar ++ "\n"
答案 0 :(得分:3)
这种ASCII网格比启发更容易混淆。让我描述一种更好的方式来表示每条可能的路径。
每个非顶行将只有一个带UP的单元格。我声称,一旦选择了每个UP单元,就可以确定LEFT和RIGHT和EMPTY单元。我声称每个非顶行中的所有可能单元可以在所有组合中都是UP。
因此,每个路径与确定UP单元格的范围(1..columns)中的(行-1)长度数列表同构。因此,允许的路径数为列^(行-1),并且以这种格式枚举可能的路径应该很容易。
然后你可以制作一台将这种格式转换为ASCII艺术品的打印机。这可能很烦人,具体取决于技能水平。
答案 1 :(得分:1)
看起来像是一个功课,所以我会尝试提供足够的提示
所以
+---+---+---+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | * |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
这里要注意的是从顶层的单元格到*
总会有一条路径。
同一行中单元格的可能路径数相同。您可以实现这一点,因为所有路径最终都必须向上移动,因为没有向下操作,因此在任何路径中,当前行上的任何单元格都可以访问当前行上方的单元格。
您可以感觉到当前单元格中所有可能的路径与左侧,右侧和上方单元格的可能路径有关。但正如我们所知,我们可以从一行中的一个单元格中找到所有可能的路径,而其余单元格的可能路径将是同一行中的一些移动,后跟该单元格中可能路径的后缀。
也许我会举个例子
+---+---+---+
| 1 | 1 | * |
+---+---+---+
| | | |
+---+---+---+
| | | |
+---+---+---+
您知道第一行中单元格的所有可能路径。您需要在第二行中找到相同的内容。因此,一个好的策略是为最正确的细胞做到这一点
+---+---+---+
| > | > | * |
+---+---+---+
| ^ | < | < |
+---+---+---+
| | | |
+---+---+---+
+---+---+---+
| | > | * |
+---+---+---+
| | ^ | < |
+---+---+---+
| | | |
+---+---+---+
+---+---+---+
| | | * |
+---+---+---+
| | | ^ |
+---+---+---+
| | | |
+---+---+---+
现在,正如我之前所说的那样,使用这些细胞可以轻松找到同一行中剩余的细胞。
最后,如果您有m X n
矩阵,则从左下角到右上角的路径数将为n^(m-1)
。
这种方式不是很优化,但易于实现。考虑m X n
网格
<
,>
,^
的确切路径。
您可以根据m
和n
找到直接公式。 喜欢
^ = m - 1
< = (n-1) * floor((m-1)/2)
> = (n-1) * (floor((m-1)/2) + 1)
permutations
中的Data.List
获取所有可能的排列。然后创建一个给定路径的函数从中剥离有效路径。将其映射到排列列表上并删除重复项。需要注意的是路径将是从排列中获得的前缀,因此对于相同的路径可以有多个排列。 答案 2 :(得分:0)
您可以创建该矩阵并定义&#34;字段&#34;?即使你不能(给出一个特定的矩阵),你也可以将[(Int, Int)]
矩阵(这对于这种任务听起来合理)映射到你自己的表示中。
由于您没有指定您的技能水平,我希望您不要介意我建议您首先尝试创建某种网格,以便有所作为:< / p>
data Status = Free | Left | Right | Up
deriving (Read, Show, Eq)
type Position = (Int, Int)
type Field = (Position, Status)
type Grid = [Field]
grid :: Grid
grid = [((x, y), stat) | x <- [1..10], y <- [1..10], let stat = Free]
当然还有其他方法可以实现这一目标。之后,您可以定义一些动作,将Position
映射到Grid
索引,将Status
es映射到可打印字符...尝试摆弄它,您可能会得到一些想法。