package com.itheima;
import java.util.ArrayList;
import java.util.List;
/**
* 第10题: 一位老农带着猫、狗、鱼过河,河边有一条船,每次老农只能带一只动物过河。当老农不和猫狗鱼在一起时,狗会咬猫,猫会吃鱼,当老农和猫狗鱼在一起时,
* 则不会发生这种问题。编程解决猫狗鱼过河问题。
*
* 答:
* ...这类型的题目没接触过,刚开始没有头绪,在草稿纸上画了几页图找出了方法,奋战多个小时,又花了大半个小时写注释...写出来后有点小开心额 呵呵~_~
* 我的算法的思路是这样的:
* 用两个List容纳各种动物,分别表示同一时刻在起点和终点
* 都有哪些动物 判断是否冲突的方法是 用两个List(dogAndCat和fishAndCat)容纳数据 一个只包含狗和猫 一个只包含猫和鱼 然后通过
* Collection.containsAll(dogAndCat或fishAndCat)的值为true或者false来判断起点或者终点有没有冲突的动物
* 用一个isHere变量来指示农夫的位置是在起点还是终点 用hereOrThere List引用变量 来指向当前位置(起点或终点)的List
*
* 流程是:
* 农夫有携带着动物的话, 就先把动物放在当前位置 (add到List中)
* 判断放下该动物后 终点是否所有动物都到齐了 是就结束程序了
*
* 否则继续执行下面的 判断:
* 如果在终点 并且终点的动物不存在冲突 那么不携带任何动物 空手折返
* 否则就拿起一个动物(通过方法判断余下的动物是否存在冲突并返回应该拿起的动物)再折返 循环搜索 直到 所有动物安全聚集在终点
*
* @author : WingsZheng
* @time : 2014年8月18日上午2:44:51
*/
public class Test10 {
// 该List用于表示同时存在狗和猫的情况
private static List<String> dogAndCat = new ArrayList<String>();
// 该List用于表示同时存在猫和鱼的情况
private static List<String> fishAndCat = new ArrayList<String>();
// 该List用于表示同时存在所有动物的情况
private static List<String> allAnimal = new ArrayList<String>();
// 该布尔变量用于判断是农夫当前在起点还是终点,设为全局变量,是用于在拿起和放下的方法中根据该变量的值,打印输出内容
private static boolean isHere = true;
// 静态初始化3个List 这3个List 配合 List.containsAll()方法来 判断是否存在冲突
static {
dogAndCat.add("dog");
dogAndCat.add("cat");
fishAndCat.add("fish");
fishAndCat.add("cat");
allAnimal.add("dog");
allAnimal.add("cat");
allAnimal.add("fish");
}
public static void main(String[] args) {
// 用于容纳起点的动物
List<String> here = allAnimal;
// 用于容纳终点的动物
List<String> there = new ArrayList<String>();
// 这个变量用来标记正在被农夫携带的动物->即拿起的动物
String getAnimal = null;
// 这个引用变量用于指向当前操作的位置 here 或者 there;
List<String> hereOrThere;
// 在一个死循环中搜索各种方案,直到终点容纳所有动物后退出循环
while (true) {
// 根据isHere为true或false,hereOrThere就指向哪个List
hereOrThere = isHere ? here : there;
// 在当前位置放下动物 如果当前没有携带动物,即getAnimal为null,该方法不会执行任何操作
dropAnimal(getAnimal, hereOrThere);
// 如果所有动物都在终点了,则表示成功,退出死循环
// !isHere表示 如果当前操作位置在起点就无需判断终点是否包含所有动物
if (!isHere && there.containsAll(allAnimal))
break;
// 没有成功则继续执行下面的操作
// 判断当前操作的位置(起点或终点) 是否存在 动物之间的冲突
// isSomeAnimalwillBeDead方法返回true就表示冲突false就表示不冲突
if (!isSomeAnimalwillBeDead(hereOrThere) && !isHere) {
// 如果不存在冲突 并且 在终点 则不拿起动物 农夫空手折返
getAnimal = null;
} else {
// 否则 拿起一个正确的动物 (拿起后留下来的动物不会冲突)
getAnimal = getCorrectAnimal(getAnimal, hereOrThere);
}
// 切换位置 表示农夫来回 如果在起点就切换到终点,反之亦然
isHere = !isHere;
}
}
/**
*
* @param getAnimal
* 表示该操作放下的动物,由农夫当前携带的动物决定
* @param hereOrThere
* 当前位置 void
*/
private static void dropAnimal(String getAnimal, List<String> hereOrThere) {
// 如果animal为空则没有任何动物被放下
if (getAnimal != null) {
hereOrThere.add(getAnimal);
//打印当前操作
System.out.println((isHere ? "在起点" : "在终点") + "放下:" + getAnimal);
}
}
/**
* 拿起正确的动物,正确的动物指的是 拿起该动物后 剩余的动物不存在冲突
*
* @param justPutDown
* 该参数传入刚刚放下的动物 , 用于过滤掉当前动物, 避免同一动物来回携带,造成死循环
* @param hereOrThere
* 传入当前位置的List
* @return 返回 正确的动物,拿起该动物 剩余的动物不存在冲突 String
*/
private static String getCorrectAnimal(String justPutDown,
List<String> hereOrThere) {
// 如果传入的刚放下的动物为null,则随意赋值 以免在下面进行equals判断时发生空指针异常
if (justPutDown == null)
justPutDown = "NoAnimal";
// 用临时变量保存List,防止在下面的循环中增删操作引起索引混乱
List<String> temp = new ArrayList<String>();
for (String string : hereOrThere) {
temp.add(string);
}
// result变量用于保存当前选定的动物,最终判断无冲突后以该值作为返回值
String result = null;
for (int i = 0; i < temp.size(); i++) {
result = temp.get(i);
// 过滤掉刚放下的动物,以免陷入死循环
if (!justPutDown.equals(result)) {
// 从当前位置删除该动物 即表示农夫拿起该动物
hereOrThere.remove(result);
// 判断拿起该动物后,剩余的动物是否存在冲突 (是否有些动物会死)
if (isSomeAnimalwillBeDead(hereOrThere)) {
// 冲突则 执行恢复操作,把拿起的动物重新放下
hereOrThere.add(result);
continue;
} else {
// 不冲突则直接退出循环 把该动物当做返回值
break;
}
}
}
// 打印当前操作
System.out.println((isHere ? "从起点" : "从终点") + "拿起:" + result);
return result;
}
/**
* 根据当前位置的List是否包含所有dogAndCat或者fishAndCat 来判断是否存在冲突情况
*
* @param hereOrThere
* 当前位置的List
* @return 是否存在冲突 true表示冲突 false表示不冲突 Boolean
*/
private static Boolean isSomeAnimalwillBeDead(List<String> hereOrThere) {
return hereOrThere.containsAll(dogAndCat)
|| hereOrThere.containsAll(fishAndCat);
}
}
老农猫、狗、鱼过河问题 黑马测试题,个人的解答.靠程序搜索答案 只给判断条件,无人为辅助判断
最新推荐文章于 2024-11-05 01:41:28 发布