Java编程能力强化(2)——搜索解决方案类问题的通用解法

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/JavaEETeacher/article/details/6167453

前几天发了一篇文章《Java编程能力强化——狼羊过河问题》,有朋友指出了一些问题,这些问题有:1、没有采用面向对象的思想,没有定义自己的类,好像与Java无关,像是C语言的编程思维。2、没有给出代码的思路。3、对是否能够提高Java编程能力表示怀疑。本文首先对第一个问题进行解释,然后给出这一类问题的通用的解决方案,然后对之前的狼羊过河代码进行分析,主要是对涉及的Java知识进行分析。

 


 

第一,编程序就是解决问题,解决问题才是硬道理

简单理解,程序就是对用户的输入进行处理,然后输出处理的结果。把人的需求表示成计算机可以理解的形式,然后由计算机进行处理,然后把计算的结果再转换为用户可以理解的形式。信息的表示是数据库结构的问题,信息的处理是算法要解决的问题,所以在计算机课程中数据结构和算法是非常重要的两门课。而数据结构和算法的实现需要一门语言,所以你可能会看到数据结构(C语言)或者数据结构(Java语言),算法通常采用伪代码。

对于狼羊过河问题,如果采用面向对象的分析,需要考虑描述中出现的对象,根据这些对象抽象出来类以及类层次,这里涉及的对象包括3只狼、3只羊、一条船,以及狼羊共存的规则以及船的容量,但是这些对象基本上没有属性和行为,所以构造成类也并不合适,所在在给出的参考代码中没有进行面向对象的设计。

另外这个题目主要是考察如何解决问题,关心的是羊和狼的数量,如何在各种约束条件下把狼和羊运送到河对岸,所以参考答案的重点是算法。

而在实现算法的过程用到了String、StringBuffer、Integer、异常处理、数组、方法的递归调用等Java语言特性,所以不能说与Java无关。

个人觉得Java中需要掌握的有3个方面的知识:基本语法、常用类库和面向对象特性,而本练习题主要是对前两个方面的强化。

 


 

第二,搜索解决方案类问题的通用解法

这类问题有下面的特点:

1、有初始状态,例如3只狼和3只羊需要过河,意味着刚开始3只狼和3只羊都在河的一个岸边。

2、有目标状态,例如3只狼和3只羊要到达河的对岸,意味着最后3只狼和3只羊都要和的对岸。

3、通过一些规则可以使状态发生变化,例如可以用船把2只狼运送到和的对岸,这时候的状态就是河的一边有3只羊和1只狼,河的另一边有2只浪(当然可以根据一边的数字推算出另一边的数字,因为要么在这边要么在那边)。

 

人是如何来解决这类问题的呢?看下面的图:

 

首先考虑3只狼3只羊在左边,船只能装两只动物,所以有5种方案,然后看看每一种方案产生的结果是不是想要的结果,如果不是,继续看有哪些情况,上面的图展示了这个过程。图中的右表示把动物运送到对岸,左表示船再回来。

 

程序如何来实现这个过程呢?

程序的实现过程是对人思考问题的模拟。有两种方式,一种方式按照层来找,初始状态下,考虑5种可能,然后对5种可能进行分析,然后对每一种情况的可能变化情况再考虑,直到找到目标状态,或者不能再变化,称为广度优先搜索。另一种方式是先考虑5种情况中的一种,考虑完之后考虑这一种情况能够转移成哪些状态,然后再考虑其中一个,称为深度优先搜索。之前给出的参考答案采用的是深度优先搜索。

例如下图,如果按照广度优先:则每个状态处理的顺序为:1(第一层) 2 3(第二层) 4 5 6(第三层) 7 8 9 10(第四层)

如果按照深度优先:则每个状态的处理顺序为:1 2 4 7 3 5 8 9 6 10,2下面的情况处理完再处理3下面的情况,同样5下面的情况处理完才处理6下面的情况。

 

算法的关键部分如下:

1、需要定义1个结构来表示状态,包括初始状态、中间状态和目标状态。我的参考代码中使用了int state[]表示状态。

2、要明确初始状态和目标状态。代码中初始状态为[3,3]表示岸上有3只狼和3只羊,目标状态为[0,0]表示狼和羊都过河了。

3、要明确状态转换的规则,通常每个规则可以定义为方法,方法的输入是一种状态,而输出是另一种状态。代码中move方法完成了这个功能,只是我把多个规则写在了同一个方法中。

4、编写主程序,从初始状态开始,不断地进行状态转换直到结束。有两种处理方式,方法的递归调用,和循环。

 

可能存在的问题:

1、死循环,最直观的例子,让一只狼到对岸,然后再回来,然后再过去,然后再回来...,永远不会有结束的时候,对于这个问题需要进行控制,有效的方式是记录走过的状态,如果发现重复,放弃这个方案。程序中有两个地方进行了控制。

2、解的空间可能会非常大,如果不采取措施可能永远也运行不完。例如下象棋,大家都知道谁想的远,谁就可能赢,如果让电脑把100步之后的情况都考虑到,我想人可能很难赢,但是让电脑考虑100步需要太大的计算量,如果考虑每一步有20种走法,则需要考虑20的100次方,可以想象这个数字有多大。对于这个问题,通常会采用启发式搜索以及剪枝等。感兴趣的同学可以参考相关书籍。


 

三、关键代码分析

完整代码参考:Java编程能力强化——狼羊过河问题

关键点分析:

1、public void next(int state[],StringBuffer str)

递归调用的方法,处理指定的状态下面的所有状态。

2、  if(str==null){ //表示第一步
   // 一只狼一只羊
   newState = move(state,"-1-1");
   next(newState,new StringBuffer("-1-1"));
   // 两只狼过河
   newState = move(state,"-2-0");
   next(newState,new StringBuffer("-2-0"));
   return;
  }
对初始状态进行处理,也可以合并在下面的代码中,如果合并需要判断str是否为空。另外,这里的return不能省略。

3、  if(state[0]==0 && state[1]==0){ // 全部转移到右岸了
   printResult(str);
   return;
  }
表示得到目标状态,处理结束。

4、   // 两只狼
   if(state[0]>=2 && !str.substring(0,4).equals("+2+0")){
    newState = move(state,"-2-0");
    if(check(newState)){
     next(newState,new StringBuffer(str).insert(0,"-2-0"));
    }
   }
注意:new StringBuffer(str).insert(0,"-2-0")不能写成
str.insert(0,"-2-0")

另外!str.substring(0,4).equals("+2+0")的作用防止去和回船上的动物是一样的。

5、 public int[] move(int state[],String info){
  int lang = 0;
  try{
   lang = Integer.parseInt(info.substring(0,2));
  }catch(Exception e){
   lang = Integer.parseInt(info.substring(1,2));
  }
  int yang = 0;
  try{
   yang= Integer.parseInt(info.substring(2));
  }catch(Exception e){
   yang = Integer.parseInt(info.substring(3));
  }
  int[] result = new int[state.length];
  result[0] = state[0]+lang;
  result[1] = state[1]+yang;
  return result;
 }

注意:try语句的使用,因为+3转换为数字的时候出现异常

另外不能直接修改state的元素值然后把state返回。

6、public boolean check(int state[]){
判定羊的个数不能小于狼的个数。

7、public boolean hasExist(StringBuffer str){
判断是否有死循环。

8、public void printResult(StringBuffer str){
输出结果方案。

大家可以试着使用广度优先的方式实现代码,可以不用递归的方式进行处理(如果递归的层数比较多,会出现堆栈溢出问题)。

展开阅读全文

木马病毒清除的通用解法

07-29

木马病毒清除的通用解法rn rn  “木马”程序会想尽一切办法隐藏自己,主要途径有:在任务栏中隐藏自己,这是最基本的只要把Form的Visible属性设为False、ShowInTaskBar设为False,程序运行时就不会出现在任务栏中了。在任务管理器中隐形:将程序设为“系统服务”可以很轻松地伪装自己。 当然它也会悄无声息地启动,你当然不会指望用户每次启动后点击“木马”图标来运行服务端,,“木马”会在每次用户启动时自动装载服务端,Windows系统启动时自动加载应用程序的方法,“木马”都会用上,如:启动组、win.ini、system.ini、注册表等等都是“木马”藏身的好地方。下面具体谈谈“木马”是怎样自动加载的。 rnrn  在win.ini文件中,在[WINDOWS]下面,“run=”和“load=”是可能加载“木马”程序的途径,必须仔细留心它们。一般情况下,它们的等号后面什么都没有,如果发现后面跟有路径与文件名不是你熟悉的启动文件,你的计算机就可能中上“木马”了。当然你也得看清楚,因为好多“木马”,如“AOL Trojan木马”,它把自身伪装成command.exe文件,如果不注意可能不会发现它不是真正的系统启动文件。 rnrn  在system.ini文件中,在[BOOT]下面有个“shell=文件名”。正确的文件名应该是“explorer.exe”,如果不是“explorer.exe”,而是“shell= explorer.exe 程序名”,那么后面跟着的那个程序就是“木马”程序,就是说你已经中“木马”了。 rnrn  在注册表中的情况最复杂,通过regedit命令打开注册表编辑器,在点击至:“HKEY-LOCAL-MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”目录下,查看键值中有没有自己不熟悉的自动启动文件,扩展名为EXE,这里切记:有的“木马”程序生成的文件很像系统自身文件,想通过伪装蒙混过关,如“Acid Battery v1.0木马”,它将注册表“HKEY-LOCAL-MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run”下的 Explorer 键值改为Explorer=“C:\WINDOWS\expiorer.exe”,“木马”程序与真正的Explorer之间只有“i”与“l”的差别。当然在注册表中还有很多地方都可以隐藏“木马”程序,如:“HKEY-CURRENT-USER\Software\Microsoft\Windows\CurrentVersion\Run”、“HKEY-USERS\****\Software\Microsoft\Windows\CurrentVersion\Run”的目录下都有可能,最好的办法就是在“HKEY-LOCAL-MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”下找到“木马”程序的文件名,再在整个注册表中搜索即可。 rnrn  知道了“木马”的工作原理,查杀“木马”就变得很容易,如果发现有“木马”存在,最安全也是最有效的方法就是马上将计算机与网络断开,防止黑客通过网络对你进行攻击。然后编辑win.ini文件,将[WINDOWS]下面,“run=“木马”程序”或“load=“木马”程序”更改为“run=”和“load=”;编辑system.ini文件,将[BOOT]下面的“shell=‘木马’文件”,更改为:“shell=explorer.exe”;在注册表中,用regedit对注册表进行编辑,先在“HKEY-LOCAL-MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”下找到“木马”程序的文件名,再在整个注册表中搜索并替换掉“木马”程序,有时候还需注意的是:有的“木马”程序并不是直接将“HKEY-LOCAL-MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”下的“木马”键值删除就行了,因为有的“木马”如:BladeRunner“木马”,如果你删除它,“木马”会立即自动加上,你需要的是记下“木马”的名字与目录,然后退回到MS-DOS下,找到此“木马”文件并删除掉。重新启动计算机,然后再到注册表中将所有“木马”文件的键值删除。 rn 论坛

转载:木马病毒的通用解法

07-27

rn注:以下转载的文章,是最通用的,也是最简单的一些通用解法,对个人而言,我认为应该随时更新自己的杀毒软件的病毒库,还得装上FIREWALL,以避免有人在你已中了木马而尚不知情的情况下,攻击你的计算机!!!!rnrnrn由于很多新手对安全问题了解不多,所以并不知道自己的计算机中了“木马”该怎么样清除。虽然现在市面上有很多新版杀毒软件都可以自动清除“木马”,但它们并不能防范新出现的“木马”程序,因此最关键的还是要知道“木马”的工作原理,这样就会很容易发现“木马”。相信你看了这篇文章之后,就会成为一名查杀“木马”的高手了。 rn  “木马”程序会想尽一切办法隐藏自己,主要途径有:在任务栏中隐藏自己,这是最基本的只要把Form的Visible属性设为False、ShowInTaskBar设为False,程序运行时就不会出现在任务栏中了。在任务管理器中隐形:将程序设为“系统服务”可以很轻松地伪装自己。 当然它也会悄无声息地启动,你当然不会指望用户每次启动后点击“木马”图标来运行服务端,,“木马”会在每次用户启动时自动装载服务端,Windows系统启动时自动加载应用程序的方法,“木马”都会用上,如:启动组、win.ini、system.ini、注册表等等都是“木马”藏身的好地方。下面具体谈谈“木马”是怎样自动加载的。 rnrn  在win.ini文件中,在[WINDOWS]下面,“run=”和“load=”是可能加载“木马”程序的途径,必须仔细留心它们。一般情况下,它们的等号后面什么都没有,如果发现后面跟有路径与文件名不是你熟悉的启动文件,你的计算机就可能中上“木马”了。当然你也得看清楚,因为好多“木马”,如“AOL Trojan木马”,它把自身伪装成command.exe文件,如果不注意可能不会发现它不是真正的系统启动文件。 rnrn  在system.ini文件中,在[BOOT]下面有个“shell=文件名”。正确的文件名应该是“explorer.exe”,如果不是“explorer.exe”,而是“shell= explorer.exe 程序名”,那么后面跟着的那个程序就是“木马”程序,就是说你已经中“木马”了。 rnrn  在注册表中的情况最复杂,通过regedit命令打开注册表编辑器,在点击至:“HKEY-LOCAL-MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”目录下,查看键值中有没有自己不熟悉的自动启动文件,扩展名为EXE,这里切记:有的“木马”程序生成的文件很像系统自身文件,想通过伪装蒙混过关,如“Acid Battery v1.0木马”,它将注册表“HKEY-LOCAL-MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run”下的 Explorer 键值改为Explorer=“C:\WINDOWS\expiorer.exe”,“木马”程序与真正的Explorer之间只有“i”与“l”的差别。当然在注册表中还有很多地方都可以隐藏“木马”程序,如:“HKEY-CURRENT-USER\Software\Microsoft\Windows\CurrentVersion\Run”、“HKEY-USERS\****\Software\Microsoft\Windows\CurrentVersion\Run”的目录下都有可能,最好的办法就是在“HKEY-LOCAL-MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”下找到“木马”程序的文件名,再在整个注册表中搜索即可。 rnrn  知道了“木马”的工作原理,查杀“木马”就变得很容易,如果发现有“木马”存在,最安全也是最有效的方法就是马上将计算机与网络断开,防止黑客通过网络对你进行攻击。然后编辑win.ini文件,将[WINDOWS]下面,“run=“木马”程序”或“load=“木马”程序”更改为“run=”和“load=”;编辑system.ini文件,将[BOOT]下面的“shell=‘木马’文件”,更改为:“shell=explorer.exe”;在注册表中,用regedit对注册表进行编辑,先在“HKEY-LOCAL-MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”下找到“木马”程序的文件名,再在整个注册表中搜索并替换掉“木马”程序,有时候还需注意的是:有的“木马”程序并不是直接将“HKEY-LOCAL-MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”下的“木马”键值删除就行了,因为有的“木马”如:BladeRunner“木马”,如果你删除它,“木马”会立即自动加上,你需要的是记下“木马”的名字与目录,然后退回到MS-DOS下,找到此“木马”文件并删除掉。重新启动计算机,然后再到注册表中将所有“木马”文件的键值删除。至此,我们就大功告成了rnrnrnby HIV 转载请注明rnrn rnrn rn 论坛

没有更多推荐了,返回首页