数据结构——农夫过河

仅仅记录个人写数据结构——农夫过河的过程

题目

题目叙述

一个农夫带着一只狼、一只羊、一颗白菜,身处河南岸,他要把这些东西全部运往北岸。现在他只有一条小船,船只能容下他和一个物品,另外只有农夫才会撑船。如果t夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,但狼不吃白菜。求出农夫将所有的东西运过河的方案。

[设计要求]

(1)构建农夫过河的状态图。
(2)写一个程序,实现上述过河方案。

思路

  1. 定义从状态0000到状态1111
  2. 农夫不在时候,狼羊和羊菜不可以在一起,如(0110,0011,1001)
  3. 0000开始,农夫可以自己过去,也可以携带和他状态相同的物品过去(如0000->1010)
  4. 所以一种状态的下一个状态有四种可能的情况:自己过去,带羊/狼/菜,
  5. 但是不是所有情况都可以变化,a:和物品状态不同,不可以变化;b:出现(2)的情况,则不可以转换
  6. 采用BFS的方法逐步确立可以变化的点,最终构建出一个树
  7. 将叶子结点即(1111)存储,用回溯的方式(存储parent)逐步读取该路,并倒叙输出(用栈)

代码

头文件

#include<iostream>
#include<queue>
#include<vector>
#include<stack>
using namespace std;

结构体

typedef struct Node{
    vector<int> locations;
    vector<struct Node*> next;
    vector<int> ex;//exist,走到该节点,前面经过的状态,状态为0~15,走过为1,否则0
    struct Node* parent;
    Node():locations(4,0),ex(16,0){}
}Node,*pNode;

主函数

int main(){
    pNode root=NULL;
    queue<pNode> leaves;
    cout<<"start"<<endl;
    creatpath(root,leaves);//构造
    printpath(leaves);//输出
    system("pause");
    return 0;
}

打印函数

void printpath(queue<pNode> leaves){
    while(!leaves.empty()){
        stack <pNode> s;
        pNode leaf = leaves.front();
        leaves.pop();

        while(leaf!=NULL){ //入栈,反向输出       
            s.push(leaf);
            leaf=leaf->parent;
        }
        while(s.size()>1){//前面带->
            pNode temp = s.top();
            s.pop();
            for(int j = 0;j < 4;j++){
                cout<<temp->locations[j];
            }
            cout<<"->";
        }
        pNode temp = s.top();
        s.pop();
        for(int j = 0;j < 4;j++){
            cout<<temp->locations[j];
        }//最后一个不带->
        cout<<endl;
    }
}

构造函数

void creatpath(pNode &r,queue<pNode> &leaves){
    queue<pNode> q;
    r = new Node;
    r->ex[0]=1;
    r->parent=NULL;
    q.push(r);
    vector<int> nextloc(4,0);
    while(!q.empty()){
        pNode root = q.front();
        q.pop();
        for(int i = 0;i < 4;i++){//构造下一状态       
            if(root->locations[0]==0){
                nextloc[0]=1;
                if(root->locations[i]==0){
                    nextloc[i]=1;
                }
                for(int j = 1;j < 4;j++){
                    if(i!=j)
                    nextloc[j]=root->locations[j];
                }
            }
            else{
                nextloc[0]=0;
                if(root->locations[i]==1){
                    nextloc[i]=0;
                }
                for(int j = 1;j < 4;j++){
                    if(i!=j)
                    nextloc[j]=root->locations[j];
                }
            }
            if(Judge(*root,nextloc)){//状态成功,则构造入树中
                pNode nextnode = new Node;
                nextnode->locations=nextloc;
                nextnode->ex=root->ex;
                nextnode->parent=root;
                root->next.push_back(nextnode);
                if(nextloc[0] == 1 && nextloc[1] == 1 && nextloc[2] == 1 && nextloc[3] == 1){
                    leaves.push(nextnode);//叶子结点
                }
                else
                    q.push(nextnode);
            }
        }
    }
}

判断函数

bool Judge(Node &root,vector<int> nextloc){
    int numh = 0;
    for(int i = 0;i < 4;i++){
        numh = numh*2+nextloc[i];
    }//转化成状态0~15
    if(root.ex[numh]==1){
        return false;
    }//走过则返回
    else{
        root.ex[numh]=1;
    }//没走过则登记为走过
    if(nextloc[0]==0){//判断狼羊菜情况
        if(nextloc[1]==1&&nextloc[2]==1||nextloc[2]==1&&nextloc[3]==1){
            return false;
        }
        else{
            return true;
        }
    }
    else{
        if(nextloc[1]==0&&nextloc[2]==0||nextloc[2]==0&&nextloc[3]==0){
            return false;
        }
        else{
            return true;
        }
    }
}

代码综合


#include<iostream>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef struct Node{
    vector<int> locations;
    vector<struct Node*> next;
    vector<int> ex;
    struct Node* parent;
    Node():locations(4,0),ex(16,0){}
}Node,*pNode;
bool Judge(Node &root,vector<int> nextloc){
    int numh = 0;
    for(int i = 0;i < 4;i++){
        numh = numh*2+nextloc[i];
    }
    if(root.ex[numh]==1){
        return false;
    }
    else{
        root.ex[numh]=1;
    }
    if(nextloc[0]==0){
        if(nextloc[1]==1&&nextloc[2]==1||nextloc[2]==1&&nextloc[3]==1){
            return false;
        }
        else{
            return true;
        }
    }
    else{
        if(nextloc[1]==0&&nextloc[2]==0||nextloc[2]==0&&nextloc[3]==0){
            return false;
        }
        else{
            return true;
        }
    }
}
void printpath(queue<pNode> leaves){
    while(!leaves.empty()){
        stack <pNode> s;
        pNode leaf = leaves.front();
        leaves.pop();

        while(leaf!=NULL){        
            s.push(leaf);
            leaf=leaf->parent;
        }
        while(s.size()>1){
            pNode temp = s.top();
            s.pop();
            for(int j = 0;j < 4;j++){
                cout<<temp->locations[j];
            }
            cout<<"->";
        }
        pNode temp = s.top();
        s.pop();
        for(int j = 0;j < 4;j++){
            cout<<temp->locations[j];
        }
        cout<<endl;
    }
}
void creatpath(pNode &r,queue<pNode> &leaves){
    queue<pNode> q;
    r = new Node;
    r->ex[0]=1;
    r->parent=NULL;
    q.push(r);
    vector<int> nextloc(4,0);
    while(!q.empty()){
        pNode root = q.front();
        q.pop();
        for(int i = 0;i < 4;i++){        
            if(root->locations[0]==0){
                nextloc[0]=1;
                if(root->locations[i]==0){
                    nextloc[i]=1;
                }
                for(int j = 1;j < 4;j++){
                    if(i!=j)
                    nextloc[j]=root->locations[j];
                }
            }
            else{
                nextloc[0]=0;
                if(root->locations[i]==1){
                    nextloc[i]=0;
                }
                for(int j = 1;j < 4;j++){
                    if(i!=j)
                    nextloc[j]=root->locations[j];
                }
            }
            if(Judge(*root,nextloc)){
                pNode nextnode = new Node;
                nextnode->locations=nextloc;
                nextnode->ex=root->ex;
                nextnode->parent=root;
                root->next.push_back(nextnode);
                if(nextloc[0] == 1 && nextloc[1] == 1 && nextloc[2] == 1 && nextloc[3] == 1){
                    leaves.push(nextnode);
                }
                else
                    q.push(nextnode);
            }
        }
    }
}
int main(){
    pNode root=NULL;
    queue<pNode> leaves;
    cout<<"start"<<endl;
    creatpath(root,leaves);
    printpath(leaves);
    system("pause");
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值