练习程序:算法系列14:狼、羊、菜和农夫过河问题

描述、思路

参考1:算法系列之十四:狼、羊、菜和农夫过河问题

补充知识

参考2:函数对象:关于仿函数、函数对象、ptr_fun
参考3:bind2nd使用

实现1

#include <iostream>
#include <deque>
#include <string>
#include <algorithm>
using namespace std;

const int action_count = 8; //一共有8种动作

int dfs_deep = 0;

int result_iter_num = 0; //打印结果时,遍历的序号

enum State{HERE, THERE}; //对象的位置:此岸,彼岸

/* 动作的代号 */
enum Action{UNKNOWN, FARMER_GO, FARMER_GO_TAKE_WOLF,
            FARMER_GO_TAKE_SHEEP, FARMER_GO_TAKE_VEGETABLE,
            FARMER_BACK, FARMER_BACK_TAKE_WOLF,
            FARMER_BACK_TAKE_SHEEP, FARMER_BACK_TAKE_VEGETABLE};
/* 打印结果时,打印的与动作的代号对应的动作全名 */
string ActionName[action_count+1] = {"Unknown action",
    "Farmer go over river", "Farmer take wolf go over river",
    "Farmer take sheep go over river", "Farmer take vegetable go over river",
    "Farmer go back", "Farmer take wolf back go back",
    "Farmer take sheep go back", "Farmer take vegetable go back"};

/* 对象状态,包含四元组状态和已执行完的最后一个动作 */
struct ItemState
{
    State farmer, wolf, sheep, vegetable; //当前四元组的状态(农夫、狼、羊、蔬菜的位置)
    Action curAction; //到达这一状态的最后一个动作(已发生)
    ItemState()
    {
        farmer = HERE;
        wolf = HERE;
        sheep = HERE;
        vegetable = HERE;
        curAction = UNKNOWN;
    }

    ItemState(State f, State w, State s, State v)
    {
        farmer = f;
        wolf = w;
        sheep = s;
        vegetable = v;
        curAction = UNKNOWN;
    }

    bool IsFinalState() //当前动作是否是结束状态
    {
        if((farmer==THERE) && (wolf==THERE) &&
           (sheep==THERE) && (vegetable==THERE))
        {
            return true;
        }
        return false;
    }

    friend bool operator == (const ItemState& is1, const ItemState& is2);

};

bool operator == (const ItemState& is1, const ItemState& is2)
{
    if((is1.farmer == is2.farmer) && (is1.sheep == is2.sheep) &&
       (is1.vegetable == is2.vegetable) && (is1.wolf == is2.wolf))
    {
        return true;
    }
    return false;
}

typedef bool (*ProcessNextFuncPtr)(const ItemState& current, ItemState& next);//函数指针

struct ActionProcess //动作处理映射结构
{
    Action act; //要执行的动作
    ProcessNextFuncPtr processFunc;//要执行的动作对应的处理流程函数指针

};

void PrintResult(const deque<ItemState> states)
{
    cout << "Find Result " << ++result_iter_num << ":" << endl;
    for(int i = 0; i < states.size(); ++i)
    {

        cout << ActionName[states[i].curAction] << ", item states is : "
             << states[i].farmer << ", " << states[i].wolf << ", "
             << states[i].sheep << ", " << states[i].vegetable << endl;
    }

}
/* 去除不合乎要求的状态,判断狼、羊不能独处,羊、菜不能独处的情况 */
bool IsCurrentStateValid(const ItemState& next)
{
    if(next.wolf == next.sheep)
    {
        if(next.wolf != next.farmer)
        {
            return false;
        }
    }
    if(next.sheep == next.vegetable)
    {
        if(next.sheep != next.farmer)
        {
            return false;
        }
    }
    return true;
}


/* 判断两个状态是否相同 */
bool IsSameItemState(ItemState& curItemState, ItemState& newState)
{
    if(((curItemState.farmer) == (newState.farmer)) &&
       ((curItemState.wolf) == (newState.wolf)) &&
       ((curItemState.sheep) == (newState.sheep)) &&
       ((curItemState.vegetable) == (newState.vegetable)))
    {
        return true;
    }
    return false;
}


/* 避免重复处理状态,检查新状态是否和状态路径上已经处理过的状态有重复 */
bool IsProcessedState(deque<ItemState>& states, ItemState& newState)
{
    for(int i = 0; i < states.size(); ++i)
    {
        if(states[i] == newState)
        {
            return true;
        }

    }
    return false;
}

/* 处理流程:农夫过河 */
bool ProcessFarmerGo(const ItemState& current, ItemState& next)
{
    //去除不可能的动作
    if(current.farmer == THERE)
    {
        return false;
    }
    next = current;
    next.farmer = THERE;
    next.curAction = FARMER_GO;
    return true;
}

/* 处理流程:农夫+狼过河 */
bool ProcessFarmerGoTakeWolf(const ItemState& current, ItemState& next)
{
    //去除不可能的动作,如果农夫在对岸,或者狼在对岸,则该动作不可进行
    if((current.farmer == THERE)|| (current.wolf == THERE))
    {
        return false;
    }
    next = current;
    next.farmer = THERE;
    next.wolf = THERE;
    next.curAction = FARMER_GO_TAKE_WOLF;
    return true;
}

/* 处理流程:农夫+羊过河 */
bool ProcessFarmerGoTakeSheep(const ItemState& current, ItemState& next)
{
    //去除不可能的动作
    if((current.farmer == THERE)||(current.sheep == THERE))
    {
        return false;
    }
    next = current;
    next.farmer = THERE;
    next.sheep = THERE;
    next.curAction = FARMER_GO_TAKE_SHEEP;
    return true;
}

/* 处理流程:农夫+菜过河 */
bool ProcessFarmerGoTakeVegetable(const ItemState& current, ItemState& next)
{
    //去除不可能的动作
    if((current.farmer == THERE)||(current.vegetable == THERE))
    {
        return false;
    }
    next = current;
    next.farmer = THERE;
    next.vegetable = THERE;
    next.curAction = FARMER_GO_TAKE_VEGETABLE;
    return true;
}

/* 处理流程:农夫返回 */
bool ProcessFarmerBack(const ItemState& current, ItemState& next)
{
    //去除不可能的动作
    if(current.farmer == HERE)
    {
        return false;
    }
    next = current;
    next.farmer = HERE;
    next.curAction = FARMER_BACK;
    return true;
}

/* 处理流程:农夫+狼返回 */
bool ProcessFarmerBackTakeWolf(const ItemState& current, ItemState& next)
{
    //去除不可能的动作,如果农夫在对岸,或者狼在对岸,则该动作不可进行
    if((current.farmer == HERE)|| (current.wolf == HERE))
    {
        return false;
    }
    next = current;
    next.farmer = HERE;
    next.wolf = HERE;
    next.curAction = FARMER_BACK_TAKE_WOLF;
    return true;
}

/* 处理流程:农夫+羊返回 */
bool ProcessFarmerBackTakeSheep(const ItemState& current, ItemState& next)
{
    //去除不可能的动作
    if((current.farmer == HERE)||(current.sheep == HERE))
    {
        return false;
    }
    next = current;
    next.farmer = HERE;
    next.sheep = HERE;
    next.curAction = FARMER_BACK_TAKE_SHEEP;
    return true;
}

/* 处理流程:农夫+菜返回 */
bool ProcessFarmerBackTakeVegetable(const ItemState& current, ItemState& next)
{
    //去除不可能的动作
    if((current.farmer == HERE)||(current.vegetable == HERE))
    {
        return false;
    }
    next = current;
    next.farmer = HERE;
    next.vegetable = HERE;
    next.curAction = FARMER_BACK_TAKE_VEGETABLE;
    return true;
}

/* 动作处理映射表 */
ActionProcess actMap[action_count] =
{
    {FARMER_GO, ProcessFarmerGo},
    {FARMER_GO_TAKE_WOLF, ProcessFarmerGoTakeWolf},
    {FARMER_GO_TAKE_SHEEP, ProcessFarmerGoTakeSheep},
    {FARMER_GO_TAKE_VEGETABLE, ProcessFarmerGoTakeVegetable},
    {FARMER_BACK, ProcessFarmerBack},
    {FARMER_BACK_TAKE_WOLF, ProcessFarmerBackTakeWolf},
    {FARMER_BACK_TAKE_SHEEP, ProcessFarmerBackTakeSheep},
    {FARMER_BACK_TAKE_VEGETABLE, ProcessFarmerBackTakeVegetable},
};

/* 递归,DFS, 穷举+剪枝,搜索并打印解 */
void ProcessState(deque<ItemState>& states)//执行动作,每次执行有8种选择
{
    //每次从状态路径中取出最后一个状态,为当前状态
    ItemState current = states.back();
    if(current.IsFinalState())
    {
        PrintResult(states);
        return;
    }
    ItemState next = ItemState();
    for(int i = 0; i < action_count; ++i)
    {
        if(actMap[i].processFunc(current, next))
        {
            if(IsCurrentStateValid(next) && (!IsProcessedState(states, next)))
            {
                states.push_back(next);//在尾部追加新状态

                //cout << ++dfs_deep << endl;
                ProcessState(states);//调用自身
                states.pop_back();//删除尾部的状态,递归依次返回

            }
        }

    }
}

int main()
{
    ItemState startItemState = ItemState();
    deque<ItemState> states;
    states.push_back(startItemState);
    /* 递归,DFS, 穷举+剪枝,搜索并打印解 */
    ProcessState(states);
    return 0;
}

实现2

用参考资料的bind2nd方法的话,新增该函数:

bool IsProcessedState_bind(deque<ItemState>& states, ItemState& newState)
{

    deque<ItemState>::iterator it =
        find_if(states.begin(), states.end(),
                bind2nd(ptr_fun(IsSameItemState),newState));
    return (it!=states.end());

}

!注意:IsSameItemState函数需要修改参数类型,不可为引用,否则编译不通过。修改IsSameItemState:

/*修改一下参数类型,去掉引用即可,函数体不变*/
bool IsSameItemState(ItemState curItemState, ItemState newState)
{
    ……
}

修改递归函数:


void ProcessState(deque<ItemState>& states)
{
    ……
    for(int i = 0; i < action_count; ++i)
    {
        if(actMap[i].processFunc(current, next))
        {
        /*修改此处,调用新增的IsProcessedState_bind,其他内容不变*/
            if(IsCurrentStateValid(next) && (!IsProcessedState_bind(states, next)))
            {
               ……
            }
        }
    }
}

运行结果

两种实现运行结果是相同的:
这里写图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章