傳教士-野人問題

來源:互聯網
上載者:User

標籤:

題目:

有N個傳教士和N個野人要過河,現在有一條船隻能承載M個人,在任何時刻,如果有野人和傳教士在一起,必須要求傳教士的人數多於或等於野人的人數(包括船上和兩個岸邊)。

設M為傳教士的人數,C為野人的人數,當N=3, M=2時, 用狀態空間法求解此問題的過程如下:

(1)設定狀態變數並確定範圍

S、C = N,B = { 0 , 1} (1表示在岸邊),要求在船上S>=C且S+C <= M

初始狀態       目標狀態

  L R
S 3 0
C 3 0
B 1 0
  L R
S 0 3
C 0 3
B 0 1

                                              

 

 

 

(2)確定狀態組,分別列出初始狀態集和目標狀態集

用三元組來表示(S , C , B)這裡面都表示的是左岸狀態

其中0<=S , C <= 3 , B∈{ 0 , 1}

(3 , 3 , 1)         (0 , 0 , 0)

初始狀態表示全部成員在河的的左岸, 目標狀態表示全部成員從河的左岸全部渡河完畢。

(3)定義並確定規則集合

        仍然以河的左岸為基點來考慮,把船從左岸劃向右岸定義為Pij操作。其中,第一個下標i表示船載的傳教士人數,第二個下標j表示船載的野人人數。同理,從右岸將船劃回左岸稱之為Qij操作,下標的定義同前。 則共有10種操作,操作集為:

                F={P10, P01,P11,P20,P02,Q10,Q01,Q11,Q20,Q02}

P10      if ( S , C , B=1 )   then ( S–1 , C , B –1 )

P01      if ( S , C , B=1 )   then ( S, C–1 , B –1 )

P11      if ( S , C , B=1 )   then ( S –1 , C–1 , B –1 )

P20      if ( S , C , B=1 )   then ( S –2 , C , B –1 )

P02      if ( S , C , B=1 )   then ( S, C–2 , B –1 )

Q10      if ( S , C , B=0 )   then ( S +1 , C , B+1 )

Q01      if ( S , C , B=0 )   then ( S, C+1 , B +1 )

Q11      if ( S , C , B=0 )   then ( S +1 , C +1, B +1 )

Q20       if ( S , C , B=0 )   then ( S +2 , C +2, B +1 )

Q02      if ( S , C, B=0 )   then ( S, C +2, B +1 )

(4)當狀態數量不是很大時,畫出合理的狀態空間圖(略)

 用廣度優先的方法,求最少次數:

#include <cstdio>#include <iostream>#include <vector>#include <queue>#include <set>using namespace std;// N is the number of scholars/cannibals, M is the boat‘s capacityint N,M;class BoatState{public:    int scholars;    int cannibals;};class LeftRiverSideState{public:    int scholars;    int cannibals;    bool isBoatOnStandby;    int countTimes;};void createBoatState(vector<BoatState> &boatStates){    //i cannibals, j scholars.    for(int i=0; i<=M; ++i)    {        for(int j=0; j<=M; ++j)        {            if(i+j>0 && i+j<=M && (i<=j||j==0))            {                BoatState bState;                bState.cannibals = i;                bState.scholars = j;                boatStates.push_back(bState);            }        }    }}void changeState(LeftRiverSideState &lrsState, queue<LeftRiverSideState> &stateQueue, vector<BoatState> &boatStates){    int countTimes = lrsState.countTimes + 1;    if(lrsState.isBoatOnStandby)    {        for(vector<BoatState>::iterator iter=boatStates.begin(); iter!=boatStates.end(); ++iter)        {            if(lrsState.cannibals >= iter->cannibals && lrsState.scholars >= iter->scholars)            {                LeftRiverSideState tmpState;                tmpState.cannibals = lrsState.cannibals - iter->cannibals;                tmpState.scholars = lrsState.scholars - iter->scholars;                tmpState.isBoatOnStandby = false;                tmpState.countTimes = countTimes;                stateQueue.push(tmpState);            }        }    }    else    {        for(vector<BoatState>::iterator iter=boatStates.begin(); iter!=boatStates.end(); ++iter)        {            if((N-lrsState.cannibals) >= iter->cannibals && (N-lrsState.scholars) >= iter->scholars)            {                LeftRiverSideState tmpState;                tmpState.cannibals = lrsState.cannibals + iter->cannibals;                tmpState.scholars = lrsState.scholars + iter->scholars;                tmpState.isBoatOnStandby = true;                tmpState.countTimes = countTimes;                stateQueue.push(tmpState);            }        }    }}int calculateMinTimes(queue<LeftRiverSideState> &stateQueue, vector<BoatState> &boatStates){    vector<LeftRiverSideState> checkState;    while(stateQueue.size() > 0)    {        LeftRiverSideState lrsState = stateQueue.front();        stateQueue.pop();        //end condition        if(lrsState.cannibals==0 && lrsState.scholars==0 && lrsState.isBoatOnStandby == false)        {            return lrsState.countTimes;        }        //check left/right river side         if( (lrsState.cannibals>lrsState.scholars && lrsState.scholars!=0) || (N-lrsState.cannibals>N-lrsState.scholars && N-lrsState.scholars!=0) )        {            continue;        }        //check endless loop        bool flag = false;        for(vector<LeftRiverSideState>::iterator iter=checkState.begin(); iter!=checkState.end(); ++iter)        {            if(iter->cannibals==lrsState.cannibals && iter->isBoatOnStandby==lrsState.isBoatOnStandby && iter->scholars==lrsState.scholars)            {                flag = true;                break;            }        }        if(flag)        {            continue;        }        checkState.push_back(lrsState);        changeState(lrsState, stateQueue, boatStates);    }    return -1;}int main(int argc, char** argv){    int tc, T;     freopen("E:/sample_input.txt", "r", stdin);    cin >> T;    for(tc = 0; tc < T; tc++)    {        cin >> N >> M;        vector<BoatState> boatStates;                createBoatState(boatStates);        LeftRiverSideState lrsState;        lrsState.cannibals = N;        lrsState.scholars = N;        lrsState.countTimes = 0;        lrsState.isBoatOnStandby = true;        queue<LeftRiverSideState> stateQueue;        stateQueue.push(lrsState);        int ret = calculateMinTimes(stateQueue, boatStates);        if(ret != -1)        {            cout << ret << endl;        }        else        {            cout << "impossible" <<endl;        }    }    return 0;}

 

傳教士-野人問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.