2.26 农夫,羊,菜和狼

题目描述
有一个农夫带一只羊、一筐菜和一只狼过河。如果没有农夫看管,则狼要吃羊,羊要吃菜。但是船很小,只够农夫带一样东西过河。问农夫该如何解此难题?

输入描述:
题目没有任何输入。

输出描述:
题目可能有种解决方法,求出步骤最少的解决方法,
按顺序输出农夫想把羊、菜、狼全部运过河需要哪几个步骤。
如果需要将羊带过河去则输出“sheep_go”。
如果需要将羊带回来则输出“sheep_come”。
如果需要将菜带过河去则输出“vegetable_go”。
如果需要将菜带回来则输出“vegetable_come”。
如果需要将狼带过河去则输出“wolf_go”。
如果需要将狼带回来则输出“wolf_come”。
如果需要空手返回则输出“nothing_come”。
如果需要空手过河则输出“nothing_go”。
每输出一种方案,输出一行“succeed”。

代码

#include
#include
using namespace std;

typedef struct Record{
    int passage;//0 vegetables ; 1 sheep ; 2 wolf ;3 nothing
    int ifgo;   //1 go ; 0 come
    Record(int a,int b):passage(a),ifgo(b){}
}Record;

vector<vector<Record> > result;  //存储可行的乘船经历
vector<Record> rec;             //记录当前状态

int goline[3]={1,1,1};              //等待过河的队伍的存在状态,1代表在,0代表不在(即在对面),3代表在渡船,下标0代表蔬菜,1代表羊,2代表狼

void goRiver(int lastPass);
void comeRiver(int lastPass);

bool ifFeasible(){
    if(goline[2]==goline[1]||goline[1]==goline[0]) return false;
    return true;
}

bool ifEnd(){
    for(int i=0;i<3;i++){
        if(goline[i]!=0) return false;
    }
    return true;
}

void goRiver(int lastPass){

    for(int i=0;i<3;i++){
        if(goline[i]&&i!=lastPass){
            goline[i]=3;
            if(ifFeasible()){
                goline[i]=0;
                Record q(i,1);
                rec.push_back(q);
                comeRiver(i);

                goline[i]=1;
                rec.pop_back();
            }else{
                goline[i]=1;
            }
        }
    }
    return;
}

void comeRiver(int lastPass){

     if(ifEnd()){
        result.push_back(rec);
        return;
    }

    if(ifFeasible()){
        Record q(3,0);
        rec.push_back(q);

        goRiver(lastPass);
        rec.pop_back();
    }else{
        for(int i=0;i<3;i++){
            if(goline[i]==0&&i!=lastPass){
                goline[i]=3;
                if(ifFeasible()){
                    goline[i]=1;
                    Record q(i,0);
                    rec.push_back(q);
                    goRiver(i);

                    goline[i]=0;
                    rec.pop_back();
                }else{
                    goline[i]=0;
                }
            }
        }
    }


    return;
}

int minRecord(){
    int minnum=10000;
    for(int i=0;i<result.size();i++){
        if(result[i].size()<minnum) minnum=result[i].size();
    }

    return minnum;
}

void printProcess(int n){

    for(int i=0;i<result[n].size();i++){
        string a,b;

        switch(result[n].at(i).passage){
            case 0:
                a="vegetable_";
                break;
            case 1:
                a="sheep_";
                break;
            case 2:
                a="wolf_";
                break;
            case 3:
                a="nothing_";
                break;
        }
        switch(result[n].at(i).ifgo){
        case 0:
            b="come";
            break;
        case 1:
            b="go";
            break;
        }

        cout<<a<<b<<endl;

    }
}
int main(){

    goRiver(-1);
    int minnum=minRecord();

    for(int i=0;i<result.size();i++){
        if(result[i].size()==minnum){
            printProcess(i);
            cout<<"succeed"<<endl;
        }
    }
}


小结:
最近因为准备复试,在学算法,这题我觉得我用的是回溯法,步骤大致如下:
1.定义一个数组goline[3]存放菜,羊,狼的状态,1代表未过河,0代表过河了,3代表正在船上
2.用回溯法,依次考虑三者过河,先考虑当它在船上时(状态为3),是否能满足没有被吃的现象,即ifFeasible(),如果满足,就过河,即状态变为0,然后又在河对岸的当前队伍中考虑回来的情况,循环;如果不满足,就又恢复原始状态为1,继续循环。
3.当每次船在河对岸时,用ifEnd()判断是否全部都渡河了

感觉代码有点长,应该还有改进的地方,慢慢看,先记录下来

你可能感兴趣的:(华科复试)