商人过河问题

问题描述:

三名商人各带一个随从过河,一只小船只能容纳两个人,随从们约定,只要在河的任何一岸,一旦随从人数多于商人人数就杀人越货,但是商人们知道了他们的约定,并且如何过河的大权掌握在商人们手中,商人们该采取怎样的策略才能安全过河呢?

问题分析(数学建模):

参考书籍: 《数学模型》 姜启源  建模示例之二

网上大部分的分析方法和书本都相同

算法分析(在问题分析的基础上进行,不懂得朋友先去看看数学建模过程):

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;
}

猜你喜欢

转载自blog.csdn.net/weixin_40571331/article/details/83216660
今日推荐