问题描述:
三名商人各带一个随从过河,一只小船只能容纳两个人,随从们约定,只要在河的任何一岸,一旦随从人数多于商人人数就杀人越货,但是商人们知道了他们的约定,并且如何过河的大权掌握在商人们手中,商人们该采取怎样的策略才能安全过河呢?
问题分析(数学建模):
参考书籍: 《数学模型》 姜启源 建模示例之二
网上大部分的分析方法和书本都相同
算法分析(在问题分析的基础上进行,不懂得朋友先去看看数学建模过程):
1.建立结构体State,用于保存每次运送前的状态
2.渡河方式一共有五种,分别是1个商人渡河(ferryM),2个商人渡河(ferryMM),1个仆人渡河(ferryS),2个仆人渡河(ferrySS),1个商人和1个仆人渡河(ferryMS),用五个函数表示
3.利用深度遍历算法(search),输入初始状态,每次寻找下一个合法的(legal)和前面没出现过的状态(equal),当下一个状态判断为最终状态时(isEndState),输出结果
4.以上括号内容均为函数名,括号前的内容即为对该函数的功能作出解释
参考链接:http://bbs.bccn.net/thread-436942-1-1.html
扫描二维码关注公众号,回复:
3659254 查看本文章
代码实现:
#include <stdio.h>
const int leftBank = 0;
const int rightBank = 1;
int count = 0;
typedef struct {
int leftMerchant;
int leftServant;
int rightMerchant;
int rightServant;
int boatLocation;
}State;
State ferryM(State s) {
if (s.boatLocation == leftBank) {
s.leftMerchant--;
s.rightMerchant++;
s.boatLocation = rightBank;
} else {
s.rightMerchant--;
s.leftMerchant++;
s.boatLocation = leftBank;
}
return s;
}
State ferryMM(State s) {
if (s.boatLocation == leftBank) {
s.leftMerchant -= 2;
s.rightMerchant += 2;
s.boatLocation = rightBank;
} else {
s.rightMerchant -= 2;
s.leftMerchant += 2;
s.boatLocation = leftBank;
}
return s;
}
State ferryS(State s) {
if (s.boatLocation == leftBank) {
s.leftServant--;
s.rightServant++;
s.boatLocation = rightBank;
} else {
s.rightServant--;
s.leftServant++;
s.boatLocation = leftBank;
}
return s;
}
State ferrySS(State s) {
if (s.boatLocation == leftBank) {
s.leftServant -= 2;
s.rightServant += 2;
s.boatLocation = rightBank;
} else {
s.rightServant -= 2;
s.leftServant += 2;
s.boatLocation = leftBank;
}
return s;
}
State ferryMS(State s) {
if (s.boatLocation == leftBank) {
s.leftMerchant--;
s.leftServant--;
s.rightMerchant++;
s.rightServant++;
s.boatLocation = rightBank;
} else {
s.leftMerchant++;
s.leftServant++;
s.rightMerchant--;
s.rightServant--;
s.boatLocation = leftBank;
}
return s;
}
State (* ferry[])(State) = {ferryM,ferryMM,ferryS,ferrySS,ferryMS};
int legal(State s) {
if (s.leftMerchant < 0) return 0;
if (s.leftServant < 0) return 0;
if (s.rightMerchant < 0) return 0;
if (s.rightServant < 0) return 0;
if (s.leftMerchant > 0 && s.leftMerchant < s.leftServant) return 0;
if (s.rightMerchant > 0 && s.rightMerchant < s.rightServant) return 0;
return 1;
}
int equal(State s1, State s2) {
if (s1.leftMerchant != s2.leftMerchant) return 0;
if (s1.leftServant != s2.leftServant) return 0;
if (s1.rightMerchant != s2.rightMerchant) return 0;
if (s1.rightServant != s2.rightServant) return 0;
if (s1.boatLocation != s2.boatLocation) return 0;
return 1;
}
int isEndState(State s) {
return s.leftMerchant == 0 &&
s.leftServant == 0 &&
s.rightMerchant == 3 &&
s.rightServant == 3 &&
s.boatLocation == rightBank;
}
void showState(State s) {
printf("M[%d]S[%d] %s M[%d]S[%d]\n", s.leftMerchant, s.leftServant,
s.boatLocation==rightBank?"~!":"!~", s.rightMerchant, s.rightServant);
}
int search(State *existingStates, int statesIndex) { //利用深度遍历,找下一个满足条件的状态
State s;
int length, i, j;
if (isEndState(existingStates[statesIndex]))
return statesIndex + 1;
for (i = 0; i < 5; i++) {
s = ferry[i](existingStates[statesIndex]);
if (!legal(s)) continue;
for (j = 0; j <= statesIndex; j++)
if (equal(existingStates[j],s))
break;
if (j <= statesIndex) continue;
existingStates[statesIndex+1] = s;
length = search(existingStates, statesIndex+1);
if (length > 0) return length;
}
return 0;
}
int main() {
State ss[32] = {{3,3,0,0,leftBank}};
int n = search(ss,0);
for (int i = 0; i < n; i++)
showState(ss[i]);
return 0;
}