**倒水问题:给定2 个没有刻度容器,对于任意给定的容积,求出如何只用两个
这道题是一个隐形的BFS题目,有其他解法,但是为了配合实验要求,我还是选用 BFS,代码看起来很长,但是只是将八种情况一一分类.
每回我们对当前状态有八种选择:
1往x灌水
2.往y灌水
3.x倒空
4. y倒空
5 y未满 , x->y 后 x空
6.y未满 x->y 后 x不空
5. x未满 ,y->x 后 y空
6. x未满,y -> x 后 y不空
只需对这八种状态进行讨论,满足要求的入队即可.已经遍历过的状态记得要用vis数
组标记,否则会无限循环,如果你忘了标记,你的电脑就会爆(别问我为什么知道!)
程序源码:
#include <iostream>
#include <queue>
#include <string>
#include<vector>
using namespace std;
int a, b, z;//a,b是x瓶和y瓶的容量 z是我们要配置的水的体积
int vis[100][100] = {
0, };//标记已经访问过的状态 起始都置为0
typedef struct state
{
int x, y;
vector<string> step;
}State;//x,y是当前两瓶中水的体积 step用来记录到达当前状态所经历的过程
//1,往x灌水 2.往y灌水 3.x倒空 4. y倒空 5 y未满 , x->y x空 6.y未满 x->y x不空 7. x未满 ,y->x y空 8.x未满,y -> x y不空
vector<string> BFS(bool &isOk)//参数用来返回是否找到合适的方法 返回的容器内容是步骤
{
queue<State> stateQ;//定义队列
State now;//定义当前状态
State next;//定义下一个状态
string tmp;//临时变量记录当前状态到下一状态的处理方式
now.x = now.y = 0;//当前状态两瓶容量均为空
stateQ.push(now);//当前状态入队列
while(stateQ.empty() == false)//队列不为空时一直执行
{
now = stateQ.front();//取队头状态
stateQ.pop();//队头状态出队
if(now.x == z || now.y == z)//当前状态某一个瓶子满足要求
{
isOk = true;//返回成功
return now.step;//如果当前x或y瓶符合要求 那么就把步骤容器返回
}
if(now.x < a && vis[a][now.y] == 0)// 如果x瓶未满 且 向x灌满水后的状态未经历过
{
next.x = a;//下一状态x瓶会满
next.y = now.y;//next即将x瓶灌满水后的状态
vis[next.x][next.y] = 1;//标记下一状态为经历过
tmp = "Lake->x\t" + to_string(next.x - now.x) ;//要向x瓶再加多少升水
tmp += "\tState : x = " + to_string(next.x) + " y = " + to_string(next.y);//下一步的状态
next.step = now.step;//把原来经历的步骤赋给next的step
next.step.push_back(tmp);//把步骤加入容器中
stateQ.push(next);//把下一个状态加入队列
}
if(now.y < b && vis[now.x][b] == 0)// 如果y瓶未满 且 向y灌满水后的状态未经历过
{
next.x = now.x;
next.y = b;//next即将x瓶灌满水后的状态
vis[next.x][next.y] = 1;
tmp = "Lake->y\t" + to_string(next.y - now.y) ;//要向y瓶再加多少升水
tmp += "\tState : x = " + to_string(next.x) + " y = " + to_string(next.y);//下一步的状态
next.step = now.step;//把原来经历的步骤赋给next的step
next.step.push_back(tmp);//把步骤加入容器中
stateQ.push(next);//把下一个状态加入队列
}
if(now.x > 0 && vis[0][now.y] == 0)// 如果x瓶有水 将x瓶水倒光
{
next.x = 0;
next.y = now.y;//next即将x瓶灌满水后的状态
vis[next.x][next.y] = 1;
tmp = "x->Lake\t" + to_string(now.x);//要向x瓶再加多少升水
tmp += "\tState : x = " + to_string(next.x) + " y = " + to_string(next.y);//下一步的状态
next.step = now.step;//把原来经历的步骤赋给next的step
next.step.push_back(tmp);//把步骤加入容器中
stateQ.push(next);//把下一个状态加入队列
}
if(now.y > 0 && vis[now.x][0] == 0)// 如果y瓶有水 将y瓶水倒光
{
next.x = now.x;
next.y = 0;//next即将x瓶灌满水后的状态
vis[next.x][next.y] = 1;
tmp = "y->Lake\t" + to_string(now.y);//要向x瓶再加多少升水
tmp += "\tState : x = " + to_string(next.x) + " y = " + to_string(next.y);//下一步的状态
next.step = now.step;//把原来经历的步骤赋给next的step
next.step.push_back(tmp);//把步骤加入容器中
stateQ.push(next);//把下一个状态加入队列
}
if(now.x > 0 && now.y < b)//x向y中倒水
{
if(now.x <= b - now.y && vis[0][now.y + now.x] == 0)//x中的水全部倒入y中 y没有溢出
{
next.x = 0;
next.y = now.y + now.x;
vis[next.x][next.y] = 1;
tmp = "x->y\t\t" + to_string(now.x);//要向y瓶再加多少升水
tmp += "\tState : x = " + to_string(next.x) + " y = " + to_string(next.y);//下一步的状态
next.step = now.step;//把原来经历的步骤赋给next的step
next.step.push_back(tmp);//把步骤加入容器中
stateQ.push(next);//把下一个状态加入队列
}
if(now.x > b - now.y && vis[now.x - (b - now.y)][b] == 0) //x中的水部分倒入y中 y可以盛满
{
next.x = now.x - (b - now.y);
next.y = b;
vis[next.x][next.y] = 1;
tmp = "x->y\t\t" + to_string(b - now.y);//要向y瓶再加多少升水
tmp += "\tState : x = " + to_string(next.x) + " y = " + to_string(next.y);//下一步的状态
next.step = now.step;//把原来经历的步骤赋给next的step
next.step.push_back(tmp);//把步骤加入容器中
stateQ.push(next);//把下一个状态加入队列
}
}
if(now.y > 0 && now.x < a)//y向x中倒水
{
if(now.y <= a - now.x && vis[now.x + now.y][0])//y中的水全部倒入x中 x没有溢出
{
next.x = now.x + now.y;
next.y = 0;
vis[next.x][next.y] = 1;
tmp = "y->x\t\t" + to_string(now.y);//要向x瓶再加多少升水
tmp += "\tState : x = " + to_string(next.x) + " y = " + to_string(next.y);//下一步的状态
next.step = now.step;//把原来经历的步骤赋给next的step
next.step.push_back(tmp);//把步骤加入容器中
stateQ.push(next);//把下一个状态加入队列
}
if(now.y > a - now.x && vis[a][now.y - (a - now.x)]) //y中的水部分倒入x中 x可以盛满
{
next.x = a;
next.y = now.y - (a - now.x);
vis[next.x][next.y] = 1;
tmp = "y->x\t\t" + to_string(a - now.x);//要向x瓶再加多少升水
tmp += "\tState : x = " + to_string(next.x) + " y = " + to_string(next.y);//
next.step = now.step;//把原来经历的步骤赋给next的step
next.step.push_back(tmp);//把步骤加入容器中
stateQ.push(next);//把下一个状态加入队列
}
}
}
isOk = false;//走出while循环则说明没有找到合适的方法
return now.step;//随便返回
}
int main()
{
vector<string> vec;//String容器用来接收步骤
vector<string>::iterator it;//用来遍历容器
int i = 1;//指示步骤数
bool isOk;
cout << "请依次输入两个瓶子的容积以及你想要配置出水的体积:";
cin >> a >> b >> z;
vec = BFS(isOk);
if(isOk)
{
for(it = vec.begin(); it != vec.end(); it++, i++){
cout << "Step " << i << " : " ;
cout << *it << endl;
}
}
else
{
cout << "Mission Impossible!" << endl;
}
return 0;
}
程序运行截图: