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

来源:互联网 发布:番茄盒子 windows 编辑:程序博客网 时间:2024/04/29 09:05

问题原型:

三只水桶条件: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 5namespace 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;}
//深度遍历的结果


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