【广度优先遍历BFS】HDU-1495 非常可乐

本文介绍了一种使用广度优先搜索算法解决三杯水问题的方法。通过定义节点结构和遍历六种倒水操作,确保了从初始状态出发能够找到使任意两个杯子水量相等的最少步骤。代码中详细展示了如何进行状态转移和状态记录,以避免重复计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
在这里插入图片描述

注解

1、遍历6种情况:a往b倒,a往c倒,b往c倒,b往a倒,c往b倒,c往a倒。
2、能倒的条件是,前一个不空,后一个不满。倒的时候分两种情况:(1)前一个的水能全部倒到后一个杯子里;(2)前一个的水只倒一部分到后一个杯子,后一个容量就满了。
3、注意初始状态和结束状态,初始状态第一个杯子为满,第二个第三个杯子为空;结束状态是有两个杯子容量相等,另一个杯子为空。
4、注意visit数组的设置。

代码

#include <iostream>
#include <queue>
#include <cstring>

using namespace std;

const int MAXN = 101;

int S, N, M;
int visit[MAXN][MAXN][MAXN];

struct Node {
    int a;
    int b;
    int c;
    int step;
};

int BFS() {
    memset(visit, 0, sizeof(visit));
    queue<Node> q;

    Node node;
    node.a = S;
    node.b = 0;
    node.c = 0;
    visit[S][0][0] = 1;

    q.push(node);

    while(q.size()>0) {
        Node top = q.front();
        q.pop();

        if(top.a==S/2 && top.b==S/2) {
            return top.step;
        } else if(top.b==S/2 && top.c==S/2) {
            return top.step;
        } else if(top.a==S/2 && top.c==S/2) {
            return top.step;
        } else {
            Node next;
            next.step = top.step+1;
            //a->b
            if(top.a && top.b!=N) {
                if(top.a >= N-top.b) {
                    next.a = top.a - (N-top.b);
                    next.b = N;
                    next.c = top.c;
                } else {
                    next.a = 0;
                    next.b = top.b+top.a;
                    next.c = top.c;
                }
                if(!visit[next.a][next.b][next.c]) {
                    q.push(next);
                    visit[next.a][next.b][next.c] = 1;
                }
            }
            //a->c
            if(top.a && top.c!=M) {
                if(top.a >= M-top.c) {
                    next.a = top.a - (M-top.c);
                    next.b = top.b;
                    next.c = M;
                } else {
                    next.a = 0;
                    next.b = top.b;
                    next.c = top.c+top.a;
                }
                if(!visit[next.a][next.b][next.c]) {
                    q.push(next);
                    visit[next.a][next.b][next.c] = 1;
                }
            }
            //b->a
            if(top.b && top.a!=S) {
                if(top.b >= S-top.a) {
                    next.a = S;
                    next.b = top.b-(S-top.a);
                    next.c = top.c;
                } else {
                    next.a = top.a+top.b;
                    next.b = 0;
                    next.c = top.c;
                }
                if(!visit[next.a][next.b][next.c]) {
                    q.push(next);
                    visit[next.a][next.b][next.c] = 1;
                }
            }
            //b->c
            if(top.b && top.c!=M) {
                if(top.b >= M-top.c) {
                    next.a = top.a;
                    next.b = top.b-(M-top.c);
                    next.c = M;
                } else {
                    next.a = top.a;
                    next.b = 0;
                    next.c = top.c+top.b;
                }
                if(!visit[next.a][next.b][next.c]) {
                    q.push(next);
                    visit[next.a][next.b][next.c] = 1;
                }
            }
            //c->a
            if(top.c && top.a!=S) {
                if(top.c >= S-top.a) {
                    next.a = S;
                    next.b = top.b;
                    next.c = top.c-(S-top.a);
                } else {
                    next.a = top.a+top.c;
                    next.b = top.b;
                    next.c = 0;
                }
                if(!visit[next.a][next.b][next.c]) {
                    q.push(next);
                    visit[next.a][next.b][next.c] = 1;
                }
            }
            //c->b
            if(top.c && top.b!=N) {
                if(top.c >= N-top.b) {
                    next.a = top.a;
                    next.b = N;
                    next.c = top.c - (N-top.b);
                } else {
                    next.a = top.a;
                    next.b = top.b+top.c;
                    next.c = 0;
                }
                if(!visit[next.a][next.b][next.c]) {
                    q.push(next);
                    visit[next.a][next.b][next.c] = 1;
                }
            }
        }
    }
    return 0;
}


int main() {

    scanf("%d %d %d", &S, &N, &M);
    while(S || N || M) {
        if(S%2) {
            printf("NO\n");
        } else {
            if(N<M) {
                swap(N, M);
            }
            int ans = BFS();
            if(ans){
                printf("%d\n", ans);
            }
            else{
                printf("NO\n");
            }
        }
        scanf("%d %d %d", &S, &N, &M);
    }

    return 0;
}

结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值