我试图制作一个程序,使用回溯在迷宫中找到哈密顿路径.它应该返回编号为迷宫的迷宫上的路径.问题是当一个堆栈倒退时,其中一个变量(它是迷宫的表示)从调用继承,而其他变量(即使它们以相同的方式被声明),也不会(这很好).我尝试了几个解决方法,包括通过创建一个单独的类来实例化,我包含了调试消息.这是代码,有一些注释可以提供帮助.
using System; namespace ConsoleApplication1 { //I made a separate class for the function class btr { public short[,] mz = new short[,] { };//tried to pull the variable out of the function,no success public void bt(int i,int j,int l) { bool ok; ok = true; Console.WriteLine("in" + '\n' + Program.print(mz,l) + 'i' + i + 'j' + j + '\n'); //debug message for entering if (i > 0 && mz[i - 1,j] == 0) { ok = false; mz[i,j] = 1; // 1 aka go up var x = new btr { }; //my attempt to avoid the problem by instantiating the function,no success... x.mz = mz; x.bt(i - 1,j,l); //When this function exits the mz variable is copied to this one. Same for all the ifs below } if (j > 0 && mz[i,j - 1] == 0) { ok = false; mz[i,j] = 2; //2 aka go left var x = new btr { }; x.mz = mz; x.bt(i,j - 1,l); } if (i < l && mz[i + 1,j] = 3;//3 aka go down var x = new btr { }; x.mz = mz; x.bt(i + 1,l); } if (j < l && mz[i,j + 1] == 0) { ok = false; mz[i,j] = 4;//4 aka go right var x = new btr { }; x.mz = mz; x.bt(i,j + 1,l); } Console.WriteLine("out" + '\n' + Program.print(mz,l) + 'i' + i + 'j' + j + '\n'); //debug message for exiting if (ok) //this is for printing the solution when it is found { mz[i,j] = 8;// 8 aka the end foreach (int x in mz) { if (x == 0) { ok = false; break; } } if (ok) Console.WriteLine("result" + '\n' + Program.print(mz,l)); } } } class Program {//this is just for preparing the first call static short[,] test = new short[2,2] { { 0,0},{ 0,0} }; static void Main(string[] args) { var x= new btr { }; x.mz = test; x.bt(0,1); } public static string print(short[,] vr,int l)//casts my array into a string that can be printed { string s = ""; for (int i = 0; i <= l; i++) { for (int j = 0; j <= l; j++) { s += vr[i,j]; } s += '\n'; } return s; } }
}
我作为测试给出了没有任何障碍的2×2迷宫(由测试声明全0表示)并且它应该输出2个解决方案,它只输出一个并且解决方案被“注入”到堆栈中.这是输出:
in 00 00 i0j0 in 30 00 i1j0 in 30 40 i1j1 in 30 41 i0j1 out 30 41 i0j1 result 38 41 out 38 41 i1j1 out 38 41 i1j0 out 38 41 i0j0
正如您所看到的,当函数退出迷宫时仍然是38 41而不是逐渐回落到00 00,因此可以计算出更多的解决方案.我和j不受影响.
解决方法
我同意在处理递归时不变性是一种有用的技术,特别是在需要反向跟踪的情况下.也就是说,它可以在处理数组时产生不必要的开销,特别是如果它们很大.
在您的场景中,因为您在进行递归调用之前知道要修改的数组的哪个元素,所以您可以在递归调用返回后简单地重置该值.从某种意义上说,您正在利用调用堆栈来保留状态 – 在这种情况下,修改了数组元素的i和j – 并使用它来恢复递归调用后的状态.
这看起来像这样:
public void bt(int i,int l) { bool ok; ok = true; Console.WriteLine("in" + '\n' + Program.print(mz,l) + 'i' + i + 'j' + j + '\n'); //debug message for entering if (i > 0 && mz[i - 1,j] == 0) { ok = false; mz[i,j] = 1; // 1 aka go up bt(i - 1,l); mz[i,j] = 0; //When this function exits the mz variable is copied to this one. Same for all the ifs below } if (j > 0 && mz[i,j - 1] == 0) { ok = false; mz[i,j] = 2; //2 aka go left bt(i,j] = 0; } if (i < l && mz[i + 1,j] = 3;//3 aka go down bt(i + 1,j] = 0; } if (j < l && mz[i,j + 1] == 0) { ok = false; mz[i,j] = 4;//4 aka go right bt(i,j] = 0; } Console.WriteLine("out" + '\n' + Program.print(mz,l) + 'i' + i + 'j' + j + '\n'); //debug message for exiting if (ok) //this is for printing the solution when it is found { mz[i,j] = 8;// 8 aka the end foreach (int x in mz) { if (x == 0) { ok = false; break; } } if (ok) Console.WriteLine("result" + '\n' + Program.print(mz,l)); } }
注意mz [i,j] = 0;每次通话后.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。