經典的過河問題:一個人(獵人)帶了:一只雞(羊),一條狗(狼),一袋米(草),遇到一條河,河邊有一條船,船太小每次只能帶一樣東西,此人如何將自己的三件物品完好的帶到對岸?
(注:若是VS2010開發工具源碼復制可直接運行,若是其他開發工具,可能要小部分修改,源碼核心算法不用改動。具體實現請查看相應注釋!此文僅供學習參考!)
程序源碼:
// CrossRiver.cpp :定義控制臺應用程序的入口點。
//開發工具:VS2010旗艦版
//系統環境:window7旗艦版
//實現語言:C語言
//作者:柳XX
//班級:計算機XXX班
//學號:20XXXXXXXXXX
#include"stdafx.h"
#include
boolisEnd(int [],int );//判斷是否結束
int_tmain(int argc, _TCHAR* argv[])
{
intA[4]={0,0,0,0};//定義人、狗、雞、米的初始狀態,此時四者都在此岸
//定義過渡狀態,包括:人自己過河,人載狗過河,人載雞過河,人載米過河,四種狀態。
//注:其中最后的一維用來標記該向量是否已被使用,使用記為1,未使用記為0,在數組中即是a[x][4]存放的變量。
inta[4][5]={{1,0,0,0,0},{1,1,0,0,0},{1,0,1,0,0},{1,0,0,1,0}};
//保存輸出的對應步驟的字符串
char* str[4]={"人劃船過河","人劃船載狗過河","人劃船載雞過河","人劃船載米過河"};
//問題描述
printf(">>>>>>>>某日,路人甲在河邊遇到了一個難題:\n");
printf("\t他帶了三件物品:一只狗、一只雞、一袋米要到河的對岸去,然而河邊的\n");
printf("\t小船載重太小,每次只允許載三件物品里的一件過河。但是,人不在的\n");
printf("\t時候,雞和米或狗和雞在一邊時,雞會去吃米,狗會去咬雞。\n");
printf(">>>>>>>>那么他該如何過河才能保證三件物品完好無損呢?\n");
printf("\n---解---過河步驟如下:\n");
//記錄步驟
int n=1;
//開始進行狀態轉移
while(!isEnd(A,4)){
for(int i=0;i<4;i++){
//當過渡狀態向量未被使用時
if(!a[i][4]){
//保存轉換中間態
int B[4];
//異或運算,求轉換態
for(int k=0;k<4;k++){
B[k]=A[k]^a[i][k] ;
}
//狀態(1,0,0,x)是不允許的,此時人在河的彼岸,有沒有載米過去,狗和雞都會出現問題。
//狀態(0,1,1,x)是不允許的,此時人在河的此岸,有沒有載米回來,狗和雞都會出現問題。
if((!B[1]&&!B[2]&&B[0])||(B[1]&&B[2]&&!B[0]))continue;
//狀態(1,x,0,0)是不允許的,此時人在河的彼岸,有沒有載狗過去,雞和米都會出現問題。
//狀態(0,x,1,1)是不允許的,此時人在河的此岸,有沒有載狗回來,雞和米都會出現問題。
elseif((!B[2]&&!B[3]&&B[0])||(B[2]&&B[3]&&!B[0]))continue;
//其它狀態允許
else {
//改變狀態
for(int j=0;j<4;j++){
A[j]=B[j];
}
//表示該狀態已被使用
a[i][4]=1;
//輸出對應的步驟描述
printf("\n-%d-%s\n",n,str[i]);//輸出相應步驟
//步驟加一
n++;
}
}
//當過渡向量已被使用時,修改其使用狀態值,以便于下一次使用。
else a[i][4]=0;
}
}
printf("\n----------------------此時,人、狗、雞、米已全部過河!\n");
system("pause");
//結束
return 0;
}
boolisEnd(int L[],int n){//判斷是否結束,只要狀態向量有一個為零,即還未結束。
for(int i=0;i
//判斷狀態向量的各個值,為零即停止循環,返回false
if(!L[i])return false;
}
//狀態向量的各個值都為1,這表示四者都已在彼岸。過河完成!
return true;
}
運行結果: