仅仅记录个人写数据结构——农夫过河的过程
题目
题目叙述
一个农夫带着一只狼、一只羊、一颗白菜,身处河南岸,他要把这些东西全部运往北岸。现在他只有一条小船,船只能容下他和一个物品,另外只有农夫才会撑船。如果t夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,但狼不吃白菜。求出农夫将所有的东西运过河的方案。
[设计要求]
(1)构建农夫过河的状态图。
(2)写一个程序,实现上述过河方案。
思路
- 定义从状态0000到状态1111
- 农夫不在时候,狼羊和羊菜不可以在一起,如(0110,0011,1001)
- 0000开始,农夫可以自己过去,也可以携带和他状态相同的物品过去(如0000->1010)
- 所以一种状态的下一个状态有四种可能的情况:自己过去,带羊/狼/菜,
- 但是不是所有情况都可以变化,a:和物品状态不同,不可以变化;b:出现(2)的情况,则不可以转换
- 采用BFS的方法逐步确立可以变化的点,最终构建出一个树
- 将叶子结点即(1111)存储,用回溯的方式(存储parent)逐步读取该路,并倒叙输出(用栈)
代码
头文件
#include<iostream>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
结构体
typedef struct Node{
vector<int> locations;
vector<struct Node*> next;
vector<int> ex;//exist,走到该节点,前面经过的状态,状态为0~15,走过为1,否则0
struct Node* parent;
Node():locations(4,0),ex(16,0){}
}Node,*pNode;
主函数
int main(){
pNode root=NULL;
queue<pNode> leaves;
cout<<"start"<<endl;
creatpath(root,leaves);//构造
printpath(leaves);//输出
system("pause");
return 0;
}
打印函数
void printpath(queue<pNode> leaves){
while(!leaves.empty()){
stack <pNode> s;
pNode leaf = leaves.front();
leaves.pop();
while(leaf!=NULL){ //入栈,反向输出
s.push(leaf);
leaf=leaf->parent;
}
while(s.size()>1){//前面带->
pNode temp = s.top();
s.pop();
for(int j = 0;j < 4;j++){
cout<<temp->locations[j];
}
cout<<"->";
}
pNode temp = s.top();
s.pop();
for(int j = 0;j < 4;j++){
cout<<temp->locations[j];
}//最后一个不带->
cout<<endl;
}
}
构造函数
void creatpath(pNode &r,queue<pNode> &leaves){
queue<pNode> q;
r = new Node;
r->ex[0]=1;
r->parent=NULL;
q.push(r);
vector<int> nextloc(4,0);
while(!q.empty()){
pNode root = q.front();
q.pop();
for(int i = 0;i < 4;i++){//构造下一状态
if(root->locations[0]==0){
nextloc[0]=1;
if(root->locations[i]==0){
nextloc[i]=1;
}
for(int j = 1;j < 4;j++){
if(i!=j)
nextloc[j]=root->locations[j];
}
}
else{
nextloc[0]=0;
if(root->locations[i]==1){
nextloc[i]=0;
}
for(int j = 1;j < 4;j++){
if(i!=j)
nextloc[j]=root->locations[j];
}
}
if(Judge(*root,nextloc)){//状态成功,则构造入树中
pNode nextnode = new Node;
nextnode->locations=nextloc;
nextnode->ex=root->ex;
nextnode->parent=root;
root->next.push_back(nextnode);
if(nextloc[0] == 1 && nextloc[1] == 1 && nextloc[2] == 1 && nextloc[3] == 1){
leaves.push(nextnode);//叶子结点
}
else
q.push(nextnode);
}
}
}
}
判断函数
bool Judge(Node &root,vector<int> nextloc){
int numh = 0;
for(int i = 0;i < 4;i++){
numh = numh*2+nextloc[i];
}//转化成状态0~15
if(root.ex[numh]==1){
return false;
}//走过则返回
else{
root.ex[numh]=1;
}//没走过则登记为走过
if(nextloc[0]==0){//判断狼羊菜情况
if(nextloc[1]==1&&nextloc[2]==1||nextloc[2]==1&&nextloc[3]==1){
return false;
}
else{
return true;
}
}
else{
if(nextloc[1]==0&&nextloc[2]==0||nextloc[2]==0&&nextloc[3]==0){
return false;
}
else{
return true;
}
}
}
代码综合
#include<iostream>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef struct Node{
vector<int> locations;
vector<struct Node*> next;
vector<int> ex;
struct Node* parent;
Node():locations(4,0),ex(16,0){}
}Node,*pNode;
bool Judge(Node &root,vector<int> nextloc){
int numh = 0;
for(int i = 0;i < 4;i++){
numh = numh*2+nextloc[i];
}
if(root.ex[numh]==1){
return false;
}
else{
root.ex[numh]=1;
}
if(nextloc[0]==0){
if(nextloc[1]==1&&nextloc[2]==1||nextloc[2]==1&&nextloc[3]==1){
return false;
}
else{
return true;
}
}
else{
if(nextloc[1]==0&&nextloc[2]==0||nextloc[2]==0&&nextloc[3]==0){
return false;
}
else{
return true;
}
}
}
void printpath(queue<pNode> leaves){
while(!leaves.empty()){
stack <pNode> s;
pNode leaf = leaves.front();
leaves.pop();
while(leaf!=NULL){
s.push(leaf);
leaf=leaf->parent;
}
while(s.size()>1){
pNode temp = s.top();
s.pop();
for(int j = 0;j < 4;j++){
cout<<temp->locations[j];
}
cout<<"->";
}
pNode temp = s.top();
s.pop();
for(int j = 0;j < 4;j++){
cout<<temp->locations[j];
}
cout<<endl;
}
}
void creatpath(pNode &r,queue<pNode> &leaves){
queue<pNode> q;
r = new Node;
r->ex[0]=1;
r->parent=NULL;
q.push(r);
vector<int> nextloc(4,0);
while(!q.empty()){
pNode root = q.front();
q.pop();
for(int i = 0;i < 4;i++){
if(root->locations[0]==0){
nextloc[0]=1;
if(root->locations[i]==0){
nextloc[i]=1;
}
for(int j = 1;j < 4;j++){
if(i!=j)
nextloc[j]=root->locations[j];
}
}
else{
nextloc[0]=0;
if(root->locations[i]==1){
nextloc[i]=0;
}
for(int j = 1;j < 4;j++){
if(i!=j)
nextloc[j]=root->locations[j];
}
}
if(Judge(*root,nextloc)){
pNode nextnode = new Node;
nextnode->locations=nextloc;
nextnode->ex=root->ex;
nextnode->parent=root;
root->next.push_back(nextnode);
if(nextloc[0] == 1 && nextloc[1] == 1 && nextloc[2] == 1 && nextloc[3] == 1){
leaves.push(nextnode);
}
else
q.push(nextnode);
}
}
}
}
int main(){
pNode root=NULL;
queue<pNode> leaves;
cout<<"start"<<endl;
creatpath(root,leaves);
printpath(leaves);
system("pause");
return 0;
}