现在的位置: 首页 > 综合 > 正文

广度搜索——分酒问题(最优解) 收藏

2013年10月23日 ⁄ 综合 ⁄ 共 12974字 ⁄ 字号 评论关闭

 

问题描述:

已知有三个容量分别为3千克、5千克和8千克的并且是没有刻度的酒瓶,3千克和5千克的瓶子均装满了酒,而8千克的瓶子为空。现要求仅用这三个酒瓶将这些酒均分为两个4千克并分别装入5千克和8千克的瓶子中。

分析:之前分析过关于分酒问题的一般情况,牵涉到搜索问题的一般算法

(1)回溯算法:不能得到最优解

(2)深度搜索算法:不能得到最优解

(3)广度搜索算法:可以得到最优解

之前已经通过回溯法对问题进行了求解,没有得到最优步骤,这里通过广度搜索算法,给出了一个最优解。

view plaincopy to clipboardprint?
  1 #include <iostream>  
  2 #include <map>  
  3 #include <queue>  
  4 using namespace std;  
  5   
  6 //定义每个状态的结构  
  7 struct SNode  
  8 {  
  9         int state[3];//状态值  
 10         int id;//状态的id(产生这个状态的序号)  
 11         int pre;//当前状态的前驱状态id(由于是广度搜索,前驱即广度搜索树中的父节点)  
 12         bool operator < (const SNode & s)const//节点存放时的比较函数  
 13         {  
 14                 return id < s.id;  
 15         }  
 16         bool operator ==(const SNode &s)const//判断节点是否相等,当存放在map中时需要判断  
 17         {  
 18                 return (state[0]== s.state[0] )&& (state[1] == s.state[1] )&& (state[2] == s.state[2]);  
 19         }  
 20 };  
 21 SNode curState;//当前节点的状态  
 22 map< int ,SNode> save;//保存中间节点的数据结构<节点id,节点结构>  
 23 int global_id = 0;//节点id通过global_id逐渐增加  
 24 int pour(int i,int j)//判断状态转移(即能否倒酒从一个容器到另一个)  
 25 {  
 26         if(i == j)  
 27                 return 0;  
 28         if(curState.state[i]<=0)  
 29                 return 0;  
 30         int empty = 0;  
 31         if(i == 0)  
 32         {  
 33                 if(j == 1)  
 34                 {  
 35                         empty = 5 - curState.state[j];  
 36                         if(curState.state[i] < empty)  
 37                                 return curState.state[i];  
 38                         else 
 39                                 return empty;  
 40                 }  
 41                 else if(j == 2)  
 42                 {  
 43                         empty = 3 - curState.state[j];  
 44                         if(curState.state[i] < empty)  
 45                                 return curState.state[i];  
 46                         else 
 47                                 return empty;  
 48                 }  
 49         }  
 50         else if(i == 1)  
 51         {  
 52                 if(j == 0)  
 53                 {  
 54                         empty = 8 - curState.state[j];  
 55                         if(curState.state[i] < empty)  
 56                                 return curState.state[i];  
 57                         else 
 58                                 return empty;  
 59                 }  
 60                 else if(j == 2)  
 61                 {  
 62                         empty = 3 - curState.state[j];  
 63                         if(curState.state[i] < empty)  
 64                                 return curState.state[i];  
 65                         else 
 66                                 return empty;  
 67                 }  
 68         }  
 69         else 
 70         {  
 71                 if(j == 0)  
 72                 {  
 73                         empty = 8 - curState.state[j];  
 74                         if(curState.state[i] < empty)  
 75                                 return curState.state[i];  
 76                         else 
 77                                 return empty;  
 78                 }  
 79                 else if(j == 1)  
 80                 {  
 81                         empty = 5 - curState.state[j];  
 82                         if(curState.state[i] < empty)  
 83                                 return curState.state[i];  
 84                         else 
 85                                 return empty;  
 86                 }  
 87         }  
 88   
 89 }  
 90 void move(int i,int j,int n)  
 91 {  
 92         curState.state[i] -=n;  
 93         curState.state[j] +=n;  
 94 }  
 95 bool hasExist()//判断是否有重复的中间状态  
 96 {  
 97         map<int,SNode>::iterator it = save.begin();  
 98         while(it!= save.end())  
 99         {  
100                 /* 
101                 if((it->second).state[0] == curState.state[0]/ 
102                                 && (it->second).state[1] == curState.state[1]/ 
103                                 && (it->second).state[2] == curState.state[2] ) 
104                                 */ 
105                 if(it->second == curState)  
106                 return true;  
107                 it++;  
108         }  
109         return false;  
110 }  
111 bool isTarget(SNode node)//到达目的状态(4,4,0)  
112 {  
113         if( node.state[0]==4 && node.state[1] == 4 && node.state[2] == 0)  
114                 return true;  
115         else 
116                 return false;  
117 }  
118 void show()//根据每个节点的前驱节点pre逆向打印出整个搜索路径  
119 {  
120   
121         int pre = curState.pre;  
122         map<int,SNode>::iterator it;  
123         cout << curState.state[0] <<  curState.state[1] << curState.state[2] << endl;  
124         while(pre != -1)  
125         {  
126                 it = save.lower_bound(pre);  
127                 curState = it->second;  
128                 cout << curState.state[0] <<  curState.state[1] << curState.state[2] << endl;  
129                 pre = curState.pre;  
130         }  
131 }  
132 int main()  
133 {  
134         int i =0,j=0;  
135         queue<SNode> queue;//广度搜索时的队列  
136         SNode initState;//初始化状态  
137         initState.id = global_id++;  
138         initState.pre = -1;  
139         initState.state[0]=8;  
140         initState.state[1]=0;  
141         initState.state[2]=0;  
142         curState = initState;  
143         int n = 0;  
144         int pre=-1;  
145         //初始化状态如对列并作为中间状态保存在save中  
146         queue.push(initState);  
147         pair<int,SNode> p(initState.id,initState);  
148         save.insert(p);  
149         while(!queue.empty())  
150         {  
151                 curState = queue.front();  
152                 queue.pop();  
153                 pre = curState.id;  
154                 for(i=0;i<3;i++)  
155                 for(j=0;j<3;j++)  
156                 {  
157                         if((n=pour(i,j))>0)  
158                         {  
159                                 move(i,j,n);//通过pour和move由当前状态转移到下一个状态  
160                                 if(!hasExist())//判断新状态是否已经存在  
161                                 {  
162                                         curState.pre = pre;  
163                                         curState.id = global_id ++;  
164                                         if(isTarget(curState))  
165                                         {  
166                                                 //如果到达了终态,打印出搜索路径  
167                                                 pair<int,SNode> p(curState.id,curState);  
168                                                 save.insert(p);  
169                                                 show();  
170                                                 return 0;  
171                                         }  
172                                         //新状态如对并作为中间状态保存在save中  
173                                         queue.push(curState);  
174                                         pair<int,SNode> p(curState.id,curState);  
175                                         save.insert(p);  
176                                 }  
177                                 //继续广度搜索到下一个状态  
178                                 move(j,i,n);  
179                         }  
180                 }  
181         }  
182 } 
  1 #include <iostream>
  2 #include <map>
  3 #include <queue>
  4 using namespace std;
  5
  6 //定义每个状态的结构
  7 struct SNode
  8 {
  9         int state[3];//状态值
 10         int id;//状态的id(产生这个状态的序号)
 11         int pre;//当前状态的前驱状态id(由于是广度搜索,前驱即广度搜索树中的父节点)
 12         bool operator < (const SNode & s)const//节点存放时的比较函数
 13         {
 14                 return id < s.id;
 15         }
 16         bool operator ==(const SNode &s)const//判断节点是否相等,当存放在map中时需要判断
 17         {
 18                 return (state[0]== s.state[0] )&& (state[1] == s.state[1] )&& (state[2] == s.state[2]);
 19         }
 20 };
 21 SNode curState;//当前节点的状态
 22 map< int ,SNode> save;//保存中间节点的数据结构<节点id,节点结构>
 23 int global_id = 0;//节点id通过global_id逐渐增加
 24 int pour(int i,int j)//判断状态转移(即能否倒酒从一个容器到另一个)
 25 {
 26         if(i == j)
 27                 return 0;
 28         if(curState.state[i]<=0)
 29                 return 0;
 30         int empty = 0;
 31         if(i == 0)
 32         {
 33                 if(j == 1)
 34                 {
 35                         empty = 5 - curState.state[j];
 36                         if(curState.state[i] < empty)
 37                                 return curState.state[i];
 38                         else
 39                                 return empty;
 40                 }
 41                 else if(j == 2)
 42                 {
 43                         empty = 3 - curState.state[j];
 44                         if(curState.state[i] < empty)
 45                                 return curState.state[i];
 46                         else
 47                                 return empty;
 48                 }
 49         }
 50         else if(i == 1)
 51         {
 52                 if(j == 0)
 53                 {
 54                         empty = 8 - curState.state[j];
 55                         if(curState.state[i] < empty)
 56                                 return curState.state[i];
 57                         else
 58                                 return empty;
 59                 }
 60                 else if(j == 2)
 61                 {
 62                         empty = 3 - curState.state[j];
 63                         if(curState.state[i] < empty)
 64                                 return curState.state[i];
 65                         else
 66                                 return empty;
 67                 }
 68         }
 69         else
 70         {
 71                 if(j == 0)
 72                 {
 73                         empty = 8 - curState.state[j];
 74                         if(curState.state[i] < empty)
 75                                 return curState.state[i];
 76                         else
 77                                 return empty;
 78                 }
 79                 else if(j == 1)
 80                 {
 81                         empty = 5 - curState.state[j];
 82                         if(curState.state[i] < empty)
 83                                 return curState.state[i];
 84                         else
 85                                 return empty;
 86                 }
 87         }
 88
 89 }
 90 void move(int i,int j,int n)
 91 {
 92         curState.state[i] -=n;
 93         curState.state[j] +=n;
 94 }
 95 bool hasExist()//判断是否有重复的中间状态
 96 {
 97         map<int,SNode>::iterator it = save.begin();
 98         while(it!= save.end())
 99         {
100                 /*
101                 if((it->second).state[0] == curState.state[0]/
102                                 && (it->second).state[1] == curState.state[1]/
103                                 && (it->second).state[2] == curState.state[2] )
104                                 */
105                 if(it->second == curState)
106                 return true;
107                 it++;
108         }
109         return false;
110 }
111 bool isTarget(SNode node)//到达目的状态(4,4,0)
112 {
113         if( node.state[0]==4 && node.state[1] == 4 && node.state[2] == 0)
114                 return true;
115         else
116                 return false;
117 }
118 void show()//根据每个节点的前驱节点pre逆向打印出整个搜索路径
119 {
120
121         int pre = curState.pre;
122         map<int,SNode>::iterator it;
123         cout << curState.state[0] <<  curState.state[1] << curState.state[2] << endl;
124         while(pre != -1)
125         {
126                 it = save.lower_bound(pre);
127                 curState = it->second;
128                 cout << curState.state[0] <<  curState.state[1] << curState.state[2] << endl;
129                 pre = curState.pre;
130         }
131 }
132 int main()
133 {
134         int i =0,j=0;
135         queue<SNode> queue;//广度搜索时的队列
136         SNode initState;//初始化状态
137         initState.id = global_id++;
138         initState.pre = -1;
139         initState.state[0]=8;
140         initState.state[1]=0;
141         initState.state[2]=0;
142         curState = initState;
143         int n = 0;
144         int pre=-1;
145         //初始化状态如对列并作为中间状态保存在save中
146         queue.push(initState);
147         pair<int,SNode> p(initState.id,initState);
148         save.insert(p);
149         while(!queue.empty())
150         {
151                 curState = queue.front();
152                 queue.pop();
153                 pre = curState.id;
154                 for(i=0;i<3;i++)
155                 for(j=0;j<3;j++)
156                 {
157                         if((n=pour(i,j))>0)
158                         {
159                                 move(i,j,n);//通过pour和move由当前状态转移到下一个状态
160                                 if(!hasExist())//判断新状态是否已经存在
161                                 {
162                                         curState.pre = pre;
163                                         curState.id = global_id ++;
164                                         if(isTarget(curState))
165                                         {
166                                                 //如果到达了终态,打印出搜索路径
167                                                 pair<int,SNode> p(curState.id,curState);
168                                                 save.insert(p);
169                                                 show();
170                                                 return 0;
171                                         }
172                                         //新状态如对并作为中间状态保存在save中
173                                         queue.push(curState);
174                                         pair<int,SNode> p(curState.id,curState);
175                                         save.insert(p);
176                                 }
177                                 //继续广度搜索到下一个状态
178                                 move(j,i,n);
179                         }
180                 }
181         }
182 }

 

 

抱歉!评论已关闭.