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个解决方案,它只输出一个并且解决方案被“注入”到堆栈中.这是输出:
in0000i0j0in3000i1j0in3040i1j1in3041i0j1out3041i0j1result3841out3841i1j1out3841i1j0out3841i0j0
正如您所看到的,当函数退出迷宫时仍然是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;每次通话后.
如果您愿意,甚至可以将mz变量放回方法参数列表中.您只处理数组的单个实例,因此将它保留为类字段还是方法参数并不重要.
总结以上是内存溢出为你收集整理的c# – 递归函数堆栈无处不在地共享一个变量全部内容,希望文章能够帮你解决c# – 递归函数堆栈无处不在地共享一个变量所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)