有三对夫妻要过河,约束条件是,根据法律,任一女子不得在其丈夫不在场的情况下与另外男子在一起,问此时这三对夫妻能否过河?

解题思路:

在任何状态下,六人以及船的位置可以用七个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>
applicationContext.xml

相关文章: