这是某安全公司的笔试题,它的题目包括几十道选择题,和一道主观题,即野人过河问题。选择题涉及智力题、计算机组成原理、正则、C语言、操作系统等方面,而主观题,则是搜索中的经典题型。
野人过河问题题意如下:
有M个牧师(也有的翻译为传教士)和C个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险. 你能不能找出一种安全的渡河方法呢(M>=C)?
可惜,在紧张的笔试过程中,我虽然想到了可能是搜索,但是,算法的不熟练导致我并不能够非常快速的将搜索算法写出来。估计笔试跪了,写出来,供后人参考吧。
其实就是五种状态:
1.两个野人过河
2.两个牧师过河
3.一个野人一个牧师过河
4.一个牧师过河
5.一个野人过河
只需对这5种状态进行搜索,直到得到问题的解,或者得到问题无解,搜索过程即终止。
野人过河问题题意如下:
有M个牧师(也有的翻译为传教士)和C个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险. 你能不能找出一种安全的渡河方法呢(M>=C)?
可惜,在紧张的笔试过程中,我虽然想到了可能是搜索,但是,算法的不熟练导致我并不能够非常快速的将搜索算法写出来。估计笔试跪了,写出来,供后人参考吧。
其实就是五种状态:
1.两个野人过河
2.两个牧师过河
3.一个野人一个牧师过河
4.一个牧师过河
5.一个野人过河
只需对这5种状态进行搜索,直到得到问题的解,或者得到问题无解,搜索过程即终止。
代码如下:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<string> vect;
bool boat = true;//true表示船在对岸
//用深度搜索的方法进行解答
bool dfs(int m,int c,int M,int C)
{
char s[30];
//非法状态
if(m<0||c<0||M<0||C<0)
return false;
//野人多于传教士,传教士会被吃掉
if((m&&c>m)||(M&&C>M))
return false;
//运送到了对岸
if((boat&&M==0&&C==0)||(!boat&&m==0&&c==0))
return true;
if(boat==true)
sprintf(s,"M=%d,C=%d,m=%d,c=%d,boat=right",M,C,m,c);
else
sprintf(s,"M=%d,C=%d,m=%d,c=%d,boat=left",M,C,m,c);
for(int i=0;i<vect.size();i++)
{
//如果此状态已存在过
if(vect[i]==s)
return false;
}
//搜索五种状态
boat = !boat;
vect.push_back(s);
if(dfs(m+2,c,M-2,C))
{
cout<<"两个传教士过河."<<endl;
return true;
}
else if(dfs(m,c+2,M,C-2))
{
cout<<"两个野人过河."<<endl;
return true;
}
else if(dfs(m+1,c+1,M-1,C-1))
{
cout<<"一个野人和一个传教士过河."<<endl;
return true;
}
else if(dfs(m+1,c,M-1,C))
{
cout<<"一个传教士过河."<<endl;
return true;
}
else if(dfs(m,c+1,M,c-1))
{
cout<<"一个野人过河."<<endl;
return true;
}
boat = !boat;
vect.pop_back();
return false;
}
int main()
{
//假设一种情况
int M=6,C=6,m=0,c=0;
char s[30];
sprintf(s,"M=%d,C=%d,m=%d,c=%d,boat=left",M,C,m,c);
cout<<s<<endl;
if(!dfs(m,c,M,C))
cout<<"can not find a solution."<<endl;
system("pause");
return 0;
}
798

被折叠的 条评论
为什么被折叠?



