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

问题描述:

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

 

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

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

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

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

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

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 }

你可能感兴趣的:(数据结构,算法,struct,iterator,iostream)