农夫过河(简洁回溯算法)

 一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会 吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。请求出农夫将所有的东西运过河的方案。

避免出现重复步骤

 

//Ex8_8
#include<iostream>
#include<vector>
#include<map>
using namespace std;
enum Res {
	wolf,sheep,greens,null
};
map<Res, int> Pass = { {wolf,0},{sheep,0},{greens,0} };		//0表示在左侧,1表示在右侧
vector<pair<map<Res, int>, int>>result = { {Pass,0 } };
bool judge(int i) {
	if (Pass[wolf]==i&&i == Pass[sheep] || (Pass[sheep] == i && i == Pass[greens]))
		return false;
	if (count(result.begin(), result.end(), result.back()) > 1)		//避免某种情况再次出现,出现死循环
		return false;
	return true;
}
void dfs(int i) {		//i为0表示从左往右,1为从右到左
	if (!judge(!i))
		return;
	if (Pass[wolf]&& Pass[sheep]&& Pass[greens] ) {
		cout << "-------------------" << endl;
		for (int i = 0; i < result.size();i++) {
			cout << (!result[i].first[wolf] ? "狼 " : "") << (!result[i].first[sheep] ? "羊 " : "") << (!result[i].first[greens] ? "菜 " : "");
			cout << (result[i].second? " <- " : " -> ");
			cout << (result[i].first[wolf] ? "狼 " : "") << (result[i].first[sheep] ? "羊 " : "") << (result[i].first[greens] ? "菜 " : "");
			cout << endl;
		}
		return;
	}
	else {
		if (i){		//当从右往左的时候可以不带东西
			result.push_back({ Pass ,!i });
			dfs(!i);
			result.pop_back();
		}
		for (auto& it : Pass) {
			if (it.second==i) {
				it.second =!it.second;
				result.push_back({ Pass ,!i });
				dfs(!i);
				result.pop_back();
				it.second = !it.second;
			}
		}
	}
}
int main() {
	cout << "箭头所指方向没有捕食关系既能共存:" << endl;
	dfs(0);
	return 0;
}

Bitset简化版 

//Ex8_8
#include<iostream>
#include<vector>
#include<bitset>
using namespace std;
bitset<4> Pass(0);
const int wolf = 1, sheep = 2, greens = 3;
vector<bitset<4>> result = { Pass };
bool judge(int i) {
	if (Pass[wolf]==i&&i == Pass[sheep] || (Pass[sheep] == i && i == Pass[greens]))
		return false;
	if (count(result.begin(), result.end(), result.back()) > 1)		//避免某种情况再次出现,出现死循环
		return false;
	return true;
}
void dfs(int dir) {		//i为0表示从左往右,1为从右到左
	if (judge(!dir)) {
		if (Pass[wolf] && Pass[sheep] && Pass[greens]) {
			cout << "-------------------" << endl;
			for (int i = 0; i < result.size(); i++) {
				cout << (!result[i][wolf] ? "狼 " : "") << (!result[i][sheep] ? "羊 " : "") << (!result[i][greens] ? "菜 " : "");
				cout << (result[i][0] ? " <- " : " -> ");
				cout << (result[i][wolf] ? "狼 " : "") << (result[i][sheep] ? "羊 " : "") << (result[i][greens] ? "菜 " : "");
				cout << endl;
			}
		}
		else {
			for (int i = 0; i <= 3; i++) {
				if (Pass[i] == dir) {
					Pass[0] = Pass[i] = !Pass[i];
					result.push_back(Pass);
					dfs(!dir);
					result.pop_back();				
					Pass[0] = Pass[i] = !Pass[i];
				}
			}
		}
	}
}
int main() {
	cout << "箭头所指方向没有捕食关系既能共存:" << endl;
	dfs(0);
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值