農夫過河問題


視頻教程地址:https://www.bilibili.com/video/av12642530/#page=19

問題:

//人狼菜羊過河問題
//==============================================================
#include<iostream>
#include<vector>
#include<queue>

using namespace std;

bool farmer(int status) //獲取每個角色的位置,0表示在起始岸,1表示在目標岸
{
return ((status & 0x08) != 0);
}
bool wolf(int status)
{
return ((status & 0x04) != 0);
}
bool cabbage(int status)
{
return ((status & 0x02) != 0);
}
bool goat(int status)
{
return ((status & 0x01) != 0);
}


bool safe(int status) //判斷當前起始岸狀態是否安全
{
if ((goat(status) == cabbage(status)) &&
(goat(status) != farmer(status)))
return false;
if ((goat(status) == wolf(status)) &&
(goat(status) != farmer(status)))
return false;
return true;
}

int main()
{
int movers , status , newstatus; //movers表示每次過河,人要攜帶的角色(包括人只身一人過河),值為1表示這個角色發生了一次過河行動
//status表示起始岸狀態,初始為0000,順序為人狼菜羊,newstatus表示中間可到達狀態
vector<int> route(16, -1); //,順序表,存儲已經訪問過的狀態(訪問過就不能再訪問了)
queue<int> moveTo; //存儲可以安全到達的中間狀態
moveTo.push(0x00); //0000是起始岸的開始狀態,四位分別代表人狼羊菜
route[0] = 0; //route第一位存儲0,表示已經訪問過,-1表示沒有訪問過

while (!moveTo.empty() && route[15] == -1)
{
status = moveTo.front();
moveTo.pop();
for (movers = 1; movers <= 8; movers <<= 1) //要攜帶的角色
{
if (farmer(status) == (bool)(status & movers)) //要攜帶的角色必須和人在同一側
{
newstatus = status ^ (0x08 | movers); //這里的按位異或操作實現了渡過去和返回的操作
if (safe(newstatus) && (route[newstatus] == -1)) //狀態是否安全
{
route[newstatus] = status;
moveTo.push(newstatus);
}
}
}
}

if (route[15] != -1) //反向打印出結果
{
cout << "The reverse path is:" << endl;
for (int status = 15; status >= 0; status = route[status])
{
cout << "The status is :" << status << endl;
if (status == 0) break;
}
}
else
cout << "No solution." << endl;
while(1);
}

總結一下:在解決這道問題時,首先是問題抽象(找出題目中的約束條件),再而是數據抽象(找出合適的數據結構來表示題目中的各種狀態),最后將約束條件和數據結構結合在一起得到最終的算法

上面的用按位異或實現渡河和返回的操作很精髓~

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



農夫過河問題 求教! 農夫過河問題 農夫過河問題實現 農夫過河問題 農夫過河問題 農夫過河問題實現 農夫過河問題 農夫過河問題 農夫過河問題 農夫過河問題
 
粤ICP备14056181号  © 2014-2021 ITdaan.com