三种水桶,等分为两半问题

问题原型:

三只水桶条件:1号8升、2号5升、3号3升,并且没有刻度。初始状态为1号桶装满水,目标状态为把水等分为2份。

思路:

建立状态模型:

状态为

struct BulketState

{

int Bulkets[3]; //如{800}{503}等

}

行为有六种(1表示得到水,-1表示倒出水,0表示不动),{1、-1、0}{1、0、-1}{0、-1、1}{0、1、-1}{-1、0、1}{-1、1、0},根据状态对行为进行遍历同时判断行为是否可行,把下一状态存入队列当中,用于判断状态是否重复,有重复时这条分支终止行为。

#pragma once

#include <vector>
#include <algorithm>
#include <iostream>


// 8 3 5
namespace fs
{
	class BulketWater
	{
	public:
		struct BulketsState
		{
			BulketsState()
			{
				for (int i = 0; i < 3; i++)
				{
					Bulket[i] = 0;
				}
			}
			int Bulket[3];
			bool operator==(const BulketsState& rhs)
			{
				return (Bulket[0] == rhs.Bulket[0] && Bulket[1] == rhs.Bulket[1] && Bulket[2] == rhs.Bulket[2]);
			}
		};
		typedef std::vector<BulketsState> StateVector;

		struct Action
		{
			int from;
			int to;
		};


		std::vector<Action> m_ActionVector;
		StateVector m_StateVector;
		char volume[3];

		friend std::ostream& operator<<(std::ostream&,const BulketsState&);

		BulketWater();
		bool IsStateAvailable(const BulketsState&);
		bool IsStateExist(const BulketsState&);
		void AddState(const BulketsState&);
		BulketsState NextState(const BulketsState&, Action&);
		void StateLoop(BulketsState,int);
		void StateLoop(BulketsState,int,bool);
	};
}

#include "stdafx.h"
#include "Bulket.h"

namespace fs
{
	std::ostream& operator<<(std::ostream& rhs, const BulketWater::BulketsState& state)
	{
		return rhs << state.Bulket[0] << state.Bulket[1] << state.Bulket[2];
	}

	BulketWater::BulketWater()
	{
		volume[0] = 8;
		volume[1] = 3;
		volume[2] = 5;

		Action action;//初始化行为空间
		for (int from = 0; from < 3; from++)
		{
			for (int to = 0; to < 3; to++)
			{
				if (from != to)
				{
					action.from = from;
					action.to = to;
					m_ActionVector.push_back(action);
				}
			}
		}
		
	}

	bool BulketWater::IsStateAvailable(const BulketsState& state)
	{
		if (state.Bulket[0] <= 8 && state.Bulket[0] >= 0 && state.Bulket[1] <= 3 && state.Bulket[1] >= 0 && state.Bulket[2] <= 5 && state.Bulket[2] >= 0 && (state.Bulket[0] + state.Bulket[1] +state.Bulket[2]) == 8)
		{
			return true;
		}
		return false;
	}

	bool BulketWater::IsStateExist(const BulketsState& state)
	{
		return std::find(m_StateVector.begin(),m_StateVector.end(),state) != m_StateVector.end();
	}

	BulketWater::BulketsState BulketWater::NextState(const BulketsState& state, Action& action)
	{
		if (!IsStateAvailable(state))
		{
			return BulketsState();
		}
		
		BulketsState temp(state);
		int dif = volume[action.to] - state.Bulket[action.to];
		if ( dif >= temp.Bulket[action.from])
		{
			temp.Bulket[action.from] = 0;
		}
		else
		{
			temp.Bulket[action.from] = state.Bulket[action.from] - (volume[action.to] - state.Bulket[action.to]);
		}

		temp.Bulket[action.to] = state.Bulket[action.to] + (state.Bulket[action.from] - temp.Bulket[action.from]);
		return temp;		
	}

	void BulketWater::StateLoop(BulketsState state,int deep)
	{		
		if (!IsStateAvailable(state) || IsStateExist(state))
		{
			return;
		}
		
		for (int i = 0; i < deep; i++)
		{
			std::cout << "-";
		}


		m_StateVector.push_back(state);
		std::cout << state << std::endl;

		for (int i = 0; i < 6; i++)
		{
			StateLoop(NextState(state,m_ActionVector.at(i)),deep + 1);
		}
	}

	void BulketWater::StateLoop(BulketsState state,int deep,bool)
	{	
		StateVector tempStateVector;//缓存临时状态
		for (int i = 0; i < 6; i++)
		{
			BulketsState temp = NextState(state,m_ActionVector.at(i));

			if (!IsStateAvailable(temp) || IsStateExist(temp))
			{
				continue;
			}

			m_StateVector.push_back(temp);
			tempStateVector.push_back(temp);

			std::cout << state;
			for (int i = 0; i < deep + 2; i++)
			{
				std::cout << "-";
			}
			std::cout << temp << std::endl;
		}

		StateVector::iterator iter;
		for (iter = tempStateVector.begin(); iter != tempStateVector.end(); iter++)
		{
			StateLoop(*iter,deep + 2,false);
		}

		return;
	}


}
//重载函数是广度和深度遍历(广度遍历函数有问题,只处理了一个叶节点)
#include "stdafx.h"
#include "Bulket.h"

int _tmain(int argc, _TCHAR* argv[])
{
	fs::BulketWater tt;
	fs::BulketWater::BulketsState state;
	state.Bulket[0] = 8;
	state.Bulket[1] = 0;
	state.Bulket[2] = 0;
	std::cout << state << std::endl;
	tt.m_StateVector.push_back(state);
	fs::BulketWater::BulketsState nothing;
	tt.StateLoop(state,0,0);

	int d;
	scanf("%d",&d);
	return 0;
}
//深度遍历的结果


//有问题的广度遍历的结果,若想得到最短路径,需要用广度遍历


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值