三个油瓶分油问题

来源:互联网 发布:福彩3d矩阵图 编辑:程序博客网 时间:2024/06/09 20:29

1.问题描述

   原问题:两个小孩去打油,一个人带了一个一斤的空瓶,另一个带了一个七两一个三两的空瓶。原计划各打一斤油,可是由于所带的钱不够,只好两人合打了一斤油,可是又没有其它工具,试仅用三个瓶子(一斤、七两、三两)精确地分成两个半斤油来。

2.算法设计

  A.将分油问题构造的多叉树存入队列oilQueue中,尽量将在数组arr中出现过的结点不要入队。

   B.将队列头结点出队,若结点未在数组arr出现过,则存入数组arr中;若结点已在数组arr中出现过,则直接出队。

   C.构造多叉树直到找到分油问题的结果结点。

   D.按照结点的n属性,寻找其父节点,即找出分油过程。

   油瓶中的油的变化规则:


3.数据结构

  Oil类具有(x,y,z)属性,存放(一斤、七两、三两)瓶里的油。

   Node类,具有Oiln属性,存放三个瓶子里的油状态,以及瓶子存放油的父节点在数组中的位置。

   队列oilQueue存放分油问题的广度优先搜索树中的节点。

   数组arr存放分油问题的广度优先搜索树中不重复的节点。

   数组result存放分油问题的结果。

   问题的起始状态<10,0,0>,问题的目标状态<5,5,0>

4.源代码(代码最好自己编写)

#include<iostream>#include<queue>using namespace std;class Oil{public:int x;int y;int z;public:Oil(){}Oil(int a,int b,int c):x(a),y(b),z(c){}~Oil(){}};class Node{public:   Oil *o;   int n;  //父节点位置public:Node(){}Node(Oil *s_o,int c):o(s_o),n(c){}~Node(){}};bool isCir(Node *node,int cnt,Node arr[1000]){for(int n=0;n<cnt;n++){if(node->o->x==arr[n].o->x && node->o->y==arr[n].o->y && node->o->z==arr[n].o->z)return true;}return false;}int main(){Oil *root = new Oil(10,0,0);Node arr[50];Node result[20];queue<Node *> oilQueue;Node *rootNode=new Node(root,-1); oilQueue.push(rootNode);Oil * oil=new Oil();int cnt=0;//数组元素个数int t=0;//队列中记录的父节点    int res=0;//记录最终结果的位置int r=0;//记录结果数组个数arr[0].o=root;    arr[0].n=-1;//建立队列,进行广度优先遍历while(!oilQueue.empty()){Oil *newOil = new Oil();Node *newNode=new Node();oil = oilQueue.front()->o;if(!isCir(oilQueue.front(),cnt,arr)){   arr[cnt].o=oilQueue.front()->o;           arr[cnt].n=oilQueue.front()->n;   cnt++;   t=cnt-1;}oilQueue.pop();//7两瓶不满时装满if(oil->y<7){newOil = new Oil();newNode = new Node();newOil->y=7;newOil->x=10-7-oil->z;newOil->z=oil->z;newNode->o=newOil;newNode->n=t;if(!isCir(newNode,cnt,arr))   oilQueue.push(newNode);}//3两瓶不满时装满if(oil->z<3){newOil = new Oil();newNode = new Node();newOil->z=3;newOil->x=10-3-oil->y;newOil->y=oil->y;newNode->o=newOil;newNode->n=t;if(!isCir(newNode,cnt,arr))   oilQueue.push(newNode);}//7两瓶不空时倒空if(oil->y>0){newOil = new Oil();newNode = new Node();newOil->y=0;newOil->x=10-oil->z;newOil->z=oil->z;newNode->o=newOil;newNode->n=t;if(!isCir(newNode,cnt,arr))   oilQueue.push(newNode);}//3两瓶不空时倒空if(oil->z>0){newOil = new Oil();newNode = new Node();newOil->z=0;newOil->x=10-oil->y;newOil->y=oil->y;newNode->o=newOil;newNode->n=t;if(!isCir(newNode,cnt,arr))   oilQueue.push(newNode);}//7两瓶中的油全倒入3两瓶if(oil->y>0 && oil->y+oil->z<=3){newOil = new Oil();newNode = new Node();newOil->y=0;newOil->z=oil->y+oil->z;newOil->x=10-oil->y-oil->z;newNode->o=newOil;newNode->n=t;if(!isCir(newNode,cnt,arr))  oilQueue.push(newNode);}//3两瓶中的油全倒入7两瓶if(oil->z>0 && oil->y+oil->z<=7){newOil = new Oil();newNode = new Node();newOil->z=0;newOil->y=oil->y+oil->z;newOil->x=10-oil->y-oil->z;newNode->o=newOil;newNode->n=t;if(!isCir(newNode,cnt,arr))   oilQueue.push(newNode);}//用3两瓶中的油装满7两瓶if(oil->y<7 && oil->y+oil->z>=7){newOil = new Oil();newNode = new Node();newOil->y=7;newOil->z=oil->y+oil->z-7;newOil->x=10-oil->y-oil->z;newNode->o=newOil;newNode->n=t;if(!isCir(newNode,cnt,arr))   oilQueue.push(newNode);}//用7两瓶中的油装满3两if(oil->z<3 && oil->y+oil->z>=3){newOil = new Oil();newNode = new Node();newOil->z=3;newOil->y=oil->y+oil->z-3;newOil->x=10-oil->y-oil->z;newNode->o=newOil;newNode->n=t;if(!isCir(newNode,cnt,arr))oilQueue.push(newNode);}}for(int q=0;q<cnt;q++){if(arr[q].o->x==5){            res=q;break;}}while(arr[res].n!=-1){result[r]=arr[res];res=arr[res].n;r++;}if(arr[res].n==-1){result[r]=arr[res];res=arr[res].n;}for(int p=r;p>=0;p--){       cout<<"<"<<result[p].o->x<<","<<result[p].o->y<<","<<result[p].o->z<<">"<<endl;}return 0;}


5.代码运行及测试


6.结论

  A.本实验采用的是盲目搜索算法中的广度优先搜索,因为是盲目搜索,使得实验的空间复杂度较大,但是采用重复的节点不再存储,使得在一定程度上降低了实验的空间复杂度。

   B.因为实验只有起始状态以及终止状态,使得实验过程中在存储节点的时候都必须检测是否达到终止状态。对于队列中每个节点的存储也需要列出所有规则进行条件判断。

   C.这个实验只是针对油瓶是(一斤、七两、三两)的问题进行解决,灵活度并不高,假设油瓶容量为其它情况,需要重新再次编写代码。


1 0
原创粉丝点击