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


问题描述:

已知有三个容量分别为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 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值