倒水问题 隐形BFS 合肥工业大学 程序设计艺术实验二

**倒水问题:给定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;
}


程序运行截图:
在这里插入图片描述

在这里插入图片描述

Guess you like

Origin blog.csdn.net/qq_42650433/article/details/106371977