农夫过河问题实现

#include <iostream>

using namespace std;

struct Condition
{
	int farmer;
	int wolf;
	int sheep;
	int cabbage;
};

//定义状态数组
Condition conditions[100];
char* action[100];

//产生某个动作之后在状态更新
void takeWolfOver(int i)
{
	action[i]="take wolf over.";
	conditions[i+1].wolf=1;
	conditions[i+1].sheep=conditions[i].sheep;
	conditions[i+1].cabbage=conditions[i].cabbage;
}

void takeWolfBack(int i)
{
	action[i]="take wolf back.";
	conditions[i+1].wolf=0;
	conditions[i+1].sheep=conditions[i].sheep;
	conditions[i+1].cabbage=conditions[i].cabbage;
}


void takeSheepOver(int i)
{
	action[i]="take sheep over.";
	conditions[i+1].wolf=conditions[i].wolf;
	conditions[i+1].sheep=1;
	conditions[i+1].cabbage=conditions[i].cabbage;
}

void takeSheepBack(int i)
{
	action[i]="take sheep back.";
	conditions[i+1].wolf=conditions[i].wolf;
	conditions[i+1].sheep=0;
	conditions[i+1].cabbage=conditions[i].cabbage;
}

void takeCabbageOver(int i)
{
	action[i]="take cabbage over.";
	conditions[i+1].wolf=conditions[i].wolf;
	conditions[i+1].sheep=conditions[i].sheep;
	conditions[i+1].cabbage=1;
}

void takeCabbageBack(int i)
{
	action[i]="take cabbage back.";
	conditions[i+1].wolf=conditions[i].wolf;
	conditions[i+1].sheep=conditions[i].sheep;
	conditions[i+1].cabbage=0;
}

//农夫单独来回
void getOverBarely(int i)
{
	action[i]="get over barely.";
	conditions[i+1].wolf=conditions[i].wolf;
	conditions[i+1].sheep=conditions[i].sheep;
	conditions[i+1].cabbage=conditions[i].cabbage;
}

void getBackBarely(int i)
{
	action[i]="get back barely.";
	conditions[i+1].wolf=conditions[i].wolf;
	conditions[i+1].sheep=conditions[i].sheep;
	conditions[i+1].cabbage=conditions[i].cabbage;
}

void showResult(int i)
{
	int c;
	for(c=0;c<i;c++)
	{
		cout<<c+1<<"."<<action[c]<<endl;
	}
	cout<<"Nice job!"<<endl;
}

void tryOneStep(int i)
{
	int c,j;
	//到达成功状态
	if(conditions[i].farmer==1&&
		conditions[i].wolf==1&&
		conditions[i].sheep==1&&
		conditions[i].cabbage==1)
	{
		showResult(i);
		return;
	}

	//到达非法状态
	if(conditions[i].farmer!=conditions[i].wolf&&conditions[i].wolf==conditions[i].sheep||
		conditions[i].farmer!=conditions[i].sheep&&conditions[i].sheep==conditions[i].cabbage)
	{
		return;
	}

	//判断是否有重复状态

	for(c=0;c<i;c++)
	{
		if(conditions[c].farmer==conditions[i].farmer&&
			conditions[c].wolf==conditions[i].wolf&&
			conditions[c].sheep==conditions[i].sheep&&
			conditions[c].cabbage==conditions[i].cabbage)
		{
			return;
		}
	}

	j=i+1;
	if(conditions[i].farmer==0)
	{
		conditions[j].farmer=1;
		getOverBarely(i);
		tryOneStep(j);

		if(conditions[i].wolf==0)
		{
			takeWolfOver(i);
			tryOneStep(j);
		}
		if(conditions[i].sheep==0)
		{
			takeSheepOver(i);
			tryOneStep(j);
		}
		if(conditions[i].cabbage==0)
		{
			takeCabbageOver(i);
			tryOneStep(j);
		}
	}else
	{
		conditions[j].farmer=0;
		getBackBarely(i);
		tryOneStep(j);

		if(conditions[i].wolf==1)
		{
			takeWolfBack(i);
			tryOneStep(j);
		}
		if(conditions[i].sheep==1)
		{
			takeSheepBack(i);
			tryOneStep(j);
		}
		if(conditions[i].cabbage==1)
		{
			takeCabbageBack(i);
			tryOneStep(j);
		}
	}
}

int main()
{
	conditions[0].farmer=0;
	conditions[0].wolf=0;
	conditions[0].sheep=0;
	conditions[0].cabbage=0;

	tryOneStep(0);

	getchar();
	return 0;
}


1. 过程回溯法。把人、狼、羊、白菜看成A、B、C、D。过河的时候从ABCD中选两个过河,在
 *          选一个回来。若发生狼跟羊、羊跟白菜在同一个岸边,且农夫不在场,则回溯.
 *
 *       2. 图的遍历。设从南岸到北岸,在南岸ABCD的各个状态是(用二进制表示):0000,在
 *          北岸的时候各个状态是:1111。所以过河问题就是从0000起始状态到1111最终状态的
 *          过程。易得,总共有16中状态。然后把每一种状态看成图的一个结点,把可以连通的
 *          结点用有向边连起来,就构成的一个有向图。从0000这个结点遍历(深度优先或者广
 *          度优先)图,遍历到1111结点则找到解。
 *
 *       3. 状态回溯法。设从南岸到北岸,在南岸ABCD的各个状态是(用二进制表示):0000,在
 *          北岸的时候各个状态是:1111。所以过河问题就是从0000起始状态到1111最终状态的
 *          过程。易得,总共有16中状态。从第一种状态0000开始搜索,搜索当前状态下可以到达的
 *          状态,搜索到一个则把这个状态看成当前状态,继续搜索。若出现当前状态搜索无可到达
 *          的状态或已遍历所有搜索出来的状态,则回溯。直到到达1111状态。
 *       
 *       4. 状态队列搜索法。跟思路3类似,只是搜索的方式不一样。思路3中用栈的思想进行深度搜索
 *          这里采用队列的思想进行广度搜索。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值