有三对夫妻要过河,约束条件是,根据法律,任一女子不得在其丈夫不在场的情况下与另外男子在一起,问此时这三对夫妻能否过河?
解题思路:
在任何状态下,六人以及船的位置可以用七个boolean来表示:
船的位置用一个 boolean 类型的变量表示:
boolean ship;
三对夫妻用两个数组表示:
boolean a[3];//丈夫的位置
boolean b[3];//妻子的位置
则问题转化为:
由状态
State { boolean ship=true;//表示船在此岸 boolean man[3]={true,true,true};//表示三名男子全在此岸 boolean woman[3]={true,true,true};//表示三名女子全在此岸 }
经过怎样的安全路径到达状态:
State { boolean ship=false; boolean man[3]={false,false,false}; boolean woman[3]={false,false,false}; }
安全路径是指:
这条路径上的所有状态均是安全(合法)的
这条路径上的所有状态转换均是安全(合法)的
判断某个状态是否安全的标准是:
任意妻子不得在其丈夫不在身边的情况下与其它男人在一起,即:
所有妻子都和她的丈夫在一起,或三名丈夫在同侧。
/** * 判断该状态是否是合法的 * * @return true为合法,false为不合法 */ public boolean isLowful() { if (man[0] == man[1] && man[1] == man[2]) return true;// 所有丈夫都在同一侧时一定是合法的 for (int i = 0; i < 3; i++) if (man[i] != woman[i]) return false;// 任意丈夫与妻子不在同一侧时一定是不合法的 return true;// 所有妻子都和丈夫在同一侧,所以是合法的 }
判断某个状态转换是否安全的标准是:
状态转换过程中船必须由一岸到了另一岸;
状态转换过程中一定有且仅有一或二名人员随船到了另一岸:
1 /** 2 * 判断两状态之间的迁移是否合法 3 * 4 * @param state1 5 * @param state2 6 * @return 合法则返回true 7 */ 8 private boolean isLowful(SpouseQuestionState state1, SpouseQuestionState state2) { 9 if (state1 == null || state2 == null) 10 return false; 11 //System.out.println(Integer.toString(state1.hashCode(),2)+"比较"+Integer.toString(state2.hashCode(),2)); 12 if (state1.ship == state2.ship) 13 return false; 14 int count = 0; 15 for (int i = 0; i < 3; i++) { 16 if (state1.man[i] == state2.man[i]) 17 continue;// 两个状态中某个人位置没有变动 18 if (state1.man[i] == state1.ship && state2.man[i] == state2.ship) { 19 count++; 20 continue; 21 } 22 // 一个人随船到了另一侧 23 return false;// 其它情况 24 } 25 for (int i = 0; i < 3; i++) { 26 if (state1.woman[i] == state2.woman[i]) 27 continue;// 两个状态中某个人位置没有变动 28 if (state1.woman[i] == state1.ship && state2.woman[i] == state2.ship) { 29 count++; 30 continue; 31 } 32 // 一个人随船到了另一侧 33 return false;// 其它情况 34 } 35 if (count == 1 || count == 2) 36 return true; 37 return true;// 超过两人乘船或无人驾驶 38 39 }
对代码进行适量的优化:
显然以下两个状态是完全等价的:
State { boolean ship=false; boolean man[3]={true,false,false}; boolean woman[3]={true,false,false}; } 和 State { boolean ship=false; boolean man[3]={false,true,false}; boolean woman[3]={false,true,false}; }
我们可以重写State的hashCode()和equals()方法,使这两个对象等价:
1 public int hashCode(){ 2 if(hash==0){ 3 for(int ti=0;ti<3;ti++) 4 for(int tj=0;tj<ti;tj++) 5 { 6 int hash1=ship?1:0; 7 for(int x=0;x<3;x++){ 8 int i=x==ti?tj:x==tj?ti:x; 9 hash1=hash1<<1; 10 hash1+=man[i]?1:0; 11 hash1=hash1<<1; 12 hash1+=woman[i]?1:0; 13 } 14 hash1+=128; 15 hash=hash1>hash?hash1:hash; 16 } 17 } 18 return hash; 19 } 20 21 public boolean equals(SpouseQuestionState object){ 22 if(this==object)return true; 23 if(object==null)return false; 24 if(object.getClass()!=this.getClass())return false; 25 return this.hashCode()==object.hashCode(); 26 }
算法设计:
使用回溯法,发现一条路走不通就返回并另选一条,一旦走到终点就将路径输出:
1 private void Digui2(State start, LinkedList<State> last, State state, StateTransition stateTransition) { 2 if (start.equals(state.getLastState())) { 3 // System.out.println("\t抵达终点"); 4 if (last.size() <= 20) { 5 for (State sta : last) { 6 System.out.println(Integer.toString(sta.hashCode(), 2)); 7 } 8 System.out.println("抵达终点,耗时"+(last.size()+1)); 9 } 10 last.pollLast(); 11 return; 12 } 13 Set<StateTransition> temp = new HashSet<>(stateTransition.getAllLowfulStateTranssitionFrom(start)); 14 // if(temp==null){ 15 // System.out.println("\t此路不通"); 16 // return; 17 // } 18 Iterator<StateTransition> iterator = temp.iterator(); 19 while (iterator.hasNext()) { 20 StateTransition sta = iterator.next(); 21 if (last.contains(sta.getEnd())) { 22 iterator.remove(); 23 } 24 } 25 // temp.removeAll(last); 26 if (temp.isEmpty()) { 27 // System.out.println("\t此路不通"); 28 last.pollLast(); 29 return; 30 } 31 for (StateTransition x : temp) { 32 last.add(start); 33 // System.out.print(x.toString()+"\t"); 34 Digui2(x.getEnd(), last, state, stateTransition); 35 } 36 last.pollLast(); 37 return; 38 }
以下为全部代码:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- bean definitions here --> <bean id="State" class="com.lille.mathModel.riverCrossing.stateImpl.SpouseQuestionState"> </bean> <bean id="StateTransition" class="com.lille.mathModel.riverCrossing.stateTransitionImpl.SpouseQuestionStateTransition"></bean> </beans>