【算法】倒水游戏(BFS|C++)

问题描述

给你两个容器(容量分别为A, B)、一台饮水机 ,问是否能够经过
有限的步骤倒水,得到容量为 C 的水

解决方案

  • 对于每一种状态,都有以下几种转移方式:
    1. A倒入B
    2. B倒入A
    3. A倒空/满
    4. B倒空/满
  • 可以转移到不同的状态。 对于每一种状态,我们需要记录是否已经被访问过了(BFS的过程)

代码

#include <bits/stdc++.h>
using namespace std;

struct Status 
{
	int a, b;
	bool operator<(const Status &s) const 
	{
		return a!=s.a ? a<s.a : b<s.b;
	}
};
queue<Status> Q;
map<Status, Status> from;

/* 递归输出方案 */
void print(Status &p) 
{
    if ( from.find(p) == from.end() || (p.a == 0&&p.b==0) )
    {
    	printf("<%d,%d>",  p.a, p.b);
        return;
    }
    print(from[p]); // 递归
    printf("-><%d,%d>",  p.a, p.b);
}

void refresh(Status &s, Status &t) 
{
    if ( from.find(t) == from.end() ) 
    { // 特判合法,加入队列
        from[t] = s;
        Q.push(t);
    }
}

void bfs(int A, int B, int C) 
{
	// 起点, 两杯水都空
	Status s,t; s.a=0; s.b=0; 
	Q.push(s);

    while (!Q.empty()) 
    {
    	// 取队首
        s = Q.front(); Q.pop();
        // 特判到达终点
        if (s.a == C || s.b == C) {
            print(s); // 输出方案
            return;
        }

        // 倒空 a 杯的水
        if (s.a > 0) {
            t.a = 0;  // 倒空
            t.b = s.b;// b 杯不变
            refresh(s, t);
        }

        // 同理,倒空 b 杯的水
        if (s.b > 0) {
            t.b = 0;  // 倒空
            t.a = s.a;// a 杯不变
            refresh(s, t);
        }

        // a 杯未满,续满 a 杯
        if (s.a < A) 
        {
        	// 续满 a 杯
        	t.a = A;  
        	t.b = s.b;
            refresh(s, t);

            // 考虑倒入
            if (s.b != 0) 
            {
                if (s.a + s.b <= A) 
                {
                    t.a = s.a + s.b;
                    t.b = 0;
           			refresh(s, t);
                } else 
                {
                    t.a = A;
                    t.b = s.a + s.b - A;
            		refresh(s, t);
                }
            }
        }

        // 同理,b 杯未满,续满 b 杯
        if (s.b < B) 
        {
            t.a = s.a;
            t.b = B;
            refresh(s, t);
            if (s.a != 0) 
            {
                if (s.a + s.b <= B) 
                {
                    t.a = 0;
                    t.b = s.a + s.b;
                    refresh(s, t);
                } else 
                {
                    t.a = s.a + s.b - B;
                    t.b = B;
                    refresh(s, t);
                }
            }
        }
    }
    printf("-1\n");
}
int main() 
{
    int a, b, c; 
    scanf("%d%d%d", &a, &b, &c);
    bfs(a, b, c);
    return 0;
}/* 26 29 11 */
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
BFS和DFS都是常用的图搜索算法。它们的区别在于搜索的策略和复杂度。引用中提到,对于给定的问题,BFS是较佳的算法BFS(广度优先搜索)是一种逐层扩展搜索的算法。它从起始节点开始,逐层遍历邻接节点,直到找到目标节点或遍历完整个图。BFS使用队列来存储待访问的节点,确保按照层级的顺序进行搜索。BFS算法的时间复杂度为O(V + E),其中V是节点的数量,E是边的数量。 DFS(深度优先搜索)是一种递归实现的搜索算法。它从起始节点开始,不断沿着路径深入直到无法继续或找到目标节点,然后回溯到上一个节点,继续探索其他路径。DFS使用栈来存储待访问的节点,它的搜索路径是深度优先的。DFS算法的时间复杂度为O(V + E),其中V是节点的数量,E是边的数量。 在实际应用中,BFS和DFS都有各自的优缺点。BFS通常用于解决最短路径和最小生成树等问题,而DFS更适合用于寻找所有可能的解,如图的连通性和拓扑排序等问题。选择使用哪种算法取决于具体的问题和需求。引用中提到,我们在学习数据结构时通常会接触到BFS和DFS算法,尤其是在图的遍历和二叉树的遍历中经常用到。 总结起来,BFS和DFS是常用的图搜索算法,它们在搜索策略和复杂度上有不同。BFS逐层扩展搜索,适用于最短路径和最小生成树等问题。DFS深度优先搜索,适用于寻找所有可能解的问题。具体选择哪种算法取决于问题的特点和需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [熬夜怒肝,图解算法BFS和DFS的直观解释](https://blog.csdn.net/c406495762/article/details/117307841)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值