我有找到所有可能路径的问题。
a a a b b
b a a a
a b b a
从0,0的起点到2,3的终点。 我需要获得所有可能的路径。
我可以采取的行动是向下移动,向右移动。
让我告诉你我被困在哪里。 我正在尝试使用递归函数。从点0,0开始,每当我可以向右移动,只有当我必须向下移动时才向右移动。
我的递归函数:
public static move(int i,int j)
{
if(possible(x,y+1))
{
move(x,y+1);
move(x+1,y);
}
}
public static bool possible(int i,int j)
{
if((i >=0 && i<3 ) && (j>=0 && j<4))
return true;
else
return false;
}
不确定我的递归移动功能。仍然需要扩大它。我不知道应该如何实施。
我能够使用该移动方法遍历角节点但是我需要该函数在从角落右上角(0,4)到达所有可能的移动时回溯。
答案 0 :(得分:6)
你需要停下来后退一大步。
第一步应该是提出方法的签名。什么是问题陈述?
找到所有可能的路径
未提及:从特定坐标开始。
因此该方法需要返回一组路径:
static Set<Path> AllPaths(Coordinate start) { /* a miracle happens */ }
好的,现在我们到了某个地方;现在很清楚我们需要什么。我们需要一组东西,我们需要一条路径,我们需要坐标。
什么是坐标?一对整数:
struct Coordinate
{
public int X { get; }
public int Y { get; }
public Coordinate(int x, int y) : this()
{
this.X = x;
this.Y = y;
}
}
完成。所以弹出堆栈;什么是路径?路径可以为空,也可以是路径后面的第一步:
sealed class Path
{
private Path() { }
private Path(Coordinate first, Path rest)
{
this.first = first;
this.rest = rest;
}
public static readonly Path Empty = new Path();
private Coordinate first;
private Path rest;
public bool IsEmpty => this == Empty;
public Coordinate First
{
get
{
if (this.IsEmpty) throw new Exception("empty!");
return first;
}
}
public Path Rest
{
get
{
if (this.IsEmpty) throw new Exception("empty!");
return rest;
}
}
public Path Append(Coordinate c) => new Path(c, this);
public IEnumerable<Coordinate> Coordinates()
{
var current = this;
while(!current.IsEmpty)
{
yield return current;
current = current.Rest;
}
}
}
完成。
现在您实施Set<T>
。您将需要执行操作“所有项目”和“将此设置与另一项联合以生成第三项”。确保集合不可变。添加新项目时,您不想更改集合;你想要一套不同的套装。添加1时,不要将3更改为4; 3和4是不同的数字。
现在您拥有了解决问题所需的所有工具;现在你可以实现
static Set<Path> AllPaths(Coordinate start)
{
/* a miracle happens */
}
那么这是如何工作的?请记住,所有递归函数都具有相同的形式:
那么琐碎的案例是什么?
static Set<Path> AllPaths(Coordinate start)
{
/* Trivial case: if the start coordinate is at the end already
then the set consists of one empty path. */
实施。
什么是递归案例?
/* Recursive case: if we're not at the end then either we can go
right, go down, or both. Solve the problem recursively for
right and / or down, union the results together, and add the
current coordinate to the top of each path, and return the
resulting set. */
实施。
这里的课程是:
答案 1 :(得分:0)
public void MoveUp(Object sender, MoveEventArgs e)
{
if (CanMoveUp(e.CurrentPosition.Y)) ...
}
public void MoveDown(Object sender, MoveEventArgs e)
{
if (CanMoveDown(e.CurrentPosition.Y)) ...
}
public void MoveLeft(Object sender, MoveEventArgs e)
{
if (CanMoveLeft(e.CurrentPosition.X)) ...
}
public void MoveRight(Object sender, MoveEventArgs e)
{
if (CanMoveRight(e.CurrentPosition.X)) ...
}
private bool CanMoveUp(double y) => (y - 1) > 0;
private bool CanMoveDown(double y) => (y + 1) < 4;
private bool CanMoveLeft(double x) => (x - 1) > 0;
private bool CanMoveRight(double x) => (x + 1) < 4;
这些值可能不正确,但如果您想要添加任何其他可能的移动障碍,您可以轻松地为每个方法添加添加内容,代码可以重复使用且易于维护。
答案 2 :(得分:0)
很难不放弃农场并提供帮助。您应该将决策逻辑分解为3个边界函数
inBoundsX x
// return true if x is in bounds, false otherwise
inBoundsY y
// return true if y is in bounds, false otherwise
inBoundsXY x,y
// return true if x and y are in bounds, false otherwise
你的递归函数应该总是验证它给出的初始状态,然后决定下一步的移动方式。
move x,y
if inBoundsXY x,y
print I am here x,y
// use InboundsX, InboundsY to decide next move.