A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© daoqin 高级黑马   /  2014-9-10 19:43  /  4060 人查看  /  18 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

花了好多天学习java基础,刚刚才提交了基础测试题,觉得最后一道题挺有意思的,第十题:一位老农带着猫、狗、鱼过河,河边有一条船,每次老农只能带一只动物过河。当老农不和猫狗鱼在一起时,狗会咬猫,猫会吃鱼,当老农和猫狗鱼在一起时,则不会发生这种问题。编程解决猫狗鱼过河问题。有木有同学和我一样的题目,可以一起讨论一下。
想了好久,最后用图论深度优先搜索解决。
思路:假设刚开始渡河的那边  人、猫、鱼、狗各个状态是(用二进制表示):0000,那么成功过河后他们的各个状态是:1111。所以过河问题就是从0000起始状态到1111最终状态的过程,因此总共有16中状态。然后把每一种状态看成图的一个结点,把可以连通的结点用有向边连起来,就构成的一个有向图。从0000这个结点遍历(深度优先搜索)图,遍历到1111结点则找到解。
附上代码,仅供参考,可能有错误,望大神指正:
  1. public class Test10 {
  2.        
  3.         private int[][] maxtri = new int[16][16]; // 邻接矩阵,存储结点是否联通
  4.         private int[][] flag = { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 0 },
  5.                         { 5, 0 }, { 6, 0 }, { 7, 0 }, { 8, 0 }, { 9, 0 }, { 10, 0 },
  6.                         { 11, 0 }, { 12, 0 }, { 13, 0 }, { 14, 0 }, { 15, 0 } };// 状态是否被访问过的数组
  7.         private Stack stack = new Stack();
  8.        
  9.         /**
  10.          * 得到状态的字符串表示 0000 四位分别代表人 猫 鱼 狗
  11.          * @param x 状态值
  12.          * @return 格式化的字符串
  13.          */
  14.         public String getFormatString(int x) {
  15.                 String X = Integer.toBinaryString(x);
  16.                 if (X.length() < 4 && X.length() >= 3) {
  17.                         X = "0" + X;
  18.                 } else if (X.length() < 3 && X.length() >= 2) {
  19.                         X = "00" + X;
  20.                 } else if (X.length() < 2 && X.length() >= 1) {
  21.                         X = "000" + X;
  22.                 }
  23.                 return X;
  24.         }
  25.         /**
  26.          * 判断两个结点是否连通
  27.          * @param x  前一个结点状态
  28.          * @param y  后一个结点状态
  29.          * @return  连通为1 ,不连通为0
  30.          */
  31.         private boolean isConnected(int x, int y) {
  32.                 String X = getFormatString(x);
  33.                 String Y = getFormatString(y);
  34.                 if (X.charAt(0) == Y.charAt(0))
  35.                         return false;
  36.                 else {
  37.                         if (X.charAt(1) != Y.charAt(1) && X.charAt(2) != Y.charAt(2)
  38.                                         && X.charAt(3) != Y.charAt(3)) {
  39.                                 return false;
  40.                         }
  41.                         else if (X.charAt(1) != Y.charAt(1) && X.charAt(2) != Y.charAt(2)) {
  42.                                 return false;
  43.                         }
  44.                         else if (X.charAt(1) != Y.charAt(1) && X.charAt(3) != Y.charAt(3)) {
  45.                                 return false;
  46.                         }
  47.                         else if (X.charAt(2) != Y.charAt(2) && X.charAt(3) != Y.charAt(3)) {
  48.                                 return false;
  49.                         }
  50.                         else if (((X.charAt(0) != X.charAt(1)) && (X.charAt(1) != Y.charAt(1)))
  51.                                         || ((X.charAt(0) != X.charAt(2)) && (X.charAt(2) != Y.charAt(2)))
  52.                                         || ((X.charAt(0) != X.charAt(3)) && (X.charAt(3) != Y.charAt(3)))) {
  53.                                 return false;
  54.                         }
  55.                         return true;
  56.                 }
  57.         }
  58.         /**
  59.          * 初始化邻接矩阵
  60.          */
  61.         public void InitMaxtri(){
  62.                 for (int i = 0; i <16; i++) {
  63.                         for (int j = 0; j < 16; j++) {
  64.                                 if(isConnected(i, j)){
  65.                                         maxtri[i][j] = 1;
  66.                                 }
  67.                                 else{
  68.                                         maxtri[i][j] = 0;
  69.                                 }
  70.                         }
  71.                 }
  72.         }
  73.         /**
  74.          * 得到与输入节点相连的一个结点
  75.          * @param x
  76.          * @return
  77.          */
  78.         public int getVetex(int x){
  79.                 for (int i = 0; i < 16; i++) {
  80.                         if(maxtri[x][i] == 1 && flag[i][1] == 0){
  81.                                 String X = getFormatString(i);
  82.                                 if((X.charAt(0)!=X.charAt(1)&&X.charAt(1)==X.charAt(3))||
  83.                                  (X.charAt(0)!=X.charAt(1)&&X.charAt(1)==X.charAt(2))){
  84.                                         continue;       
  85.                             }
  86.                             else {
  87.                                     return i;
  88.                                 }
  89.                         }
  90.                 }
  91.                 return -1;
  92.         }
  93.         /**
  94.          * 深度优先搜索
  95.          */
  96.         public void DFS(){
  97.                 stack.push(0);
  98.                 flag[0][1]=1;
  99.                 while(!stack.isEmpty()){
  100.                         if(stack.getTop() == 15){
  101.                                 break;
  102.                         }
  103.                         int Vetex = getVetex(stack.getTop());
  104.                         if(Vetex==-1){
  105.                                 try{
  106.                                         stack.pop();
  107.                                 }catch(Exception e){
  108.                                         e.printStackTrace();
  109.                                 }
  110.                         }
  111.                         else{
  112.                                 stack.push(Vetex);
  113.                                 flag[Vetex][1] = 1;
  114.                         }
  115.                 }
  116.                        
  117.         }
  118.         /**
  119.          * 打印结果
  120.          * @throws Exception
  121.          */
  122.         public void printOrder() throws Exception{
  123.                   for(int i=0;i< stack.getLength()-1;i++){
  124.                         int x=stack.seekByIndex(i);
  125.                         int y=stack.seekByIndex(i+1);
  126.                         String X=getFormatString(x);
  127.                         String Y=getFormatString(y);
  128.                         String type="";
  129.                         if(X.charAt(0)=='0'){
  130.                                 type="过河";
  131.                         }
  132.                         if(X.charAt(0)=='1'){
  133.                                 type="回来";
  134.                         }
  135.                         if(X.charAt(1)!=Y.charAt(1)){
  136.                                 System.out.println("人带猫"+type);
  137.                         }
  138.                         else if(X.charAt(2)!=Y.charAt(2)){
  139.                                 System.out.println("人带鱼"+type);
  140.                         }
  141.                         else if(X.charAt(3)!=Y.charAt(3)){
  142.                                 System.out.println("人带狗"+type);
  143.                         }
  144.                         else{
  145.                                 System.out.println("人自己"+type);
  146.                         }
  147.                 }
  148.         }
  149.         public static void main(String[] args) {
  150.                 // TODO Auto-generated method stub
  151.                 Test10 test = new Test10();
  152.                 test.InitMaxtri();
  153.                 test.DFS();
  154.                 try{
  155.                         test.printOrder();
  156.                 }catch(Exception e){
  157.                         e.printStackTrace();
  158.                 }
  159.         }
  160.         /**
  161.          * 数据栈
  162.          * @author daoqin
  163.          */
  164.         public class Stack{
  165.                
  166.                 private int[] num;
  167.                 private int top;
  168.                 public Stack(){
  169.                         InitStack();
  170.                 }
  171.                 public void InitStack(){
  172.                         top = -1;
  173.                         num = new int[16];
  174.                 }
  175.                 public int getTop(){
  176.                         return num[top];
  177.                 }
  178.                 public int pop() throws Exception{
  179.                         if(top>=0){
  180.                                 return num[top--];
  181.                         }
  182.                         else{
  183.                                 throw new Exception("栈空");
  184.                         }
  185.                 }
  186.                 public void push(int x){
  187.                                 num[++top]=x;
  188.                 }
  189.                 public boolean isEmpty(){
  190.                         return (top<0);
  191.                 }
  192.                 public int getLength(){
  193.                         return top+1;
  194.                 }
  195.                 public int seekByIndex(int index)throws Exception{
  196.                         if(index < getLength() && index >= 0){
  197.                         return num[index];
  198.                         }
  199.                         else {
  200.                                 throw new Exception("未找到元素!");
  201.                         }
  202.                 }
  203.         }
  204. }
复制代码



评分

参与人数 1技术分 +1 收起 理由
舍我其谁 + 1 赞一个!

查看全部评分

18 个回复

倒序浏览
好复杂的说
回复 使用道具 举报

从何说起啊?
回复 使用道具 举报
代码我还没看,光前面把这16种状态想成二进制的主意就要赞一个!
回复 使用道具 举报 1 0

为什么不用集合做呢,不过你用矩阵确实是一个很新颖的想法哦
回复 使用道具 举报
Fightin黑马 发表于 2014-9-10 21:30
为什么不用集合做呢,不过你用矩阵确实是一个很新颖的想法哦

感觉用集合来做判断条件太多,因为这个状态太多了,不容易操作,当然集合做也挺好的。
回复 使用道具 举报
daoqin 发表于 2014-9-10 21:57
感觉用集合来做判断条件太多,因为这个状态太多了,不容易操作,当然集合做也挺好的。 ...

用集合做的话最起码代码阅读性要高一点,矩阵的话我反正看的挺晕的
回复 使用道具 举报
daoqin 来自手机 高级黑马 2014-9-10 23:48:11
8#
恩,同学,你接触过图论吗?没有的话可以去看看,真心觉得挺有用的
回复 使用道具 举报
clh 中级黑马 2014-9-11 02:39:31
9#
基础测试这么难啊
回复 使用道具 举报
没学过这些算法很头痛啊
回复 使用道具 举报
好难呀,,这是神马。。
回复 使用道具 举报
发现大家习惯了用集合做各种题目,有时候效率很重要,集合写起来虽简单,却容易误导我们的思维!
回复 使用道具 举报
weiyi 中级黑马 2014-10-2 14:35:54
13#
好复杂啊
回复 使用道具 举报
楼主的基础测试这么难。。
回复 使用道具 举报
楼主的思维也比较神奇,这么复杂的代码,竟然给写出来了。
回复 使用道具 举报
残羹夜宴丶 发表于 2014-10-3 08:39
楼主的思维也比较神奇,这么复杂的代码,竟然给写出来了。

亲,这个题目不难,代码不复杂的!别人用的回溯才复杂!
回复 使用道具 举报
哇塞!楼主学过数据结构吗?我也学过,但是我这是第一次见到将图运用起来的例子!赞一个!
回复 使用道具 举报
很少回帖,切实的赞一个,方法很好。Q553403028,有时间可以交流下,我算法可能比不上你。呵呵
回复 使用道具 举报
学习了,这个想法真的很6
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马