算法学习–分酒问题(BFS)[通俗易懂]

算法学习–分酒问题(BFS)[通俗易懂]有4个红酒瓶子,它们的容量分别是:9升,7升,4升,2升开始的状态是[9,0,0,0],也就是说:第一个瓶子满着,其它的都空着。允许把酒从一个瓶子倒入另一个瓶子,但只能把一个瓶子倒满或把一个瓶子倒空,不能有中间状态。这样的一次倒酒动作称为1次操作。假设瓶子的容量和初始状态不变,对于给定的目标状态,至少需要多少次操作才能实现?本题就是要求你编程实现最小操作次数的计算。输入:最终状…


Jetbrains全系列IDE稳定放心使用

有4个红酒瓶子,它们的容量分别是:9升, 7升, 4升, 2升
开始的状态是 [9,0,0,0],也就是说:第一个瓶子满着,其它的都空着。

允许把酒从一个瓶子倒入另一个瓶子,但只能把一个瓶子倒满或把一个瓶子倒空,不能有中间状态。
这样的一次倒酒动作称为1次操作。

假设瓶子的容量和初始状态不变,对于给定的目标状态,至少需要多少次操作才能实现?
本题就是要求你编程实现最小操作次数的计算。

输入:最终状态(空格分隔)
输出:最小操作次数(如无法实现,则输出-1)

例如:
输入:
9 0 0 0
应该输出:
0

输入:
6 0 0 3
应该输出:
-1

输入:
7 2 0 0
应该输出:
2

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <set>
using namespace std;

//状态类
class state { 
   
public:
	string str;//目前状态
	int step;//从原始状态到目前状态需要的步骤数
	state(string s, int st) :str(s), step(st) { 
   }
};

char glass[4] = { 
    '9','7','4','2' };//四个杯子的容量 

int bfs(string target) { 
   
	set<string> s;
	queue<state> q;
	q.push(state("9000", 0));//初始状态加入队列
	s.insert("9000");
	while (!q.empty()) { 
   
		state tmp = q.front();//取出第一个元素 
		q.pop();//弹出第一个元素 
		if (tmp.str == target) { 
   
			return tmp.step;
		}
		int k = tmp.step;
		//尝试从第i个杯子倒到第j个杯子 
		for (int i = 0; i < 4; i++) { 
   
			for (int j = 0; j < 4; j++) { 
   
				if (i == j)continue;//不能自己倒给自己 
				//1.把自己倒完(目标杯子现有量+要倒入的量<=目标杯子容量)主要看别的杯子能否装的下
				if (tmp.str[i] + tmp.str[j] - '0' <= glass[j]) { 
   
					string temp = tmp.str;
					temp[j] += temp[i] - '0';
					temp[i] = '0';
					if (s.find(temp) == s.end()) { 
   //如果这个状态之前没有出现过,就加入到集合中
						s.insert(temp);
						q.push(state(temp, k + 1));
					}
				}
				//2.把别的杯子装满 主要看自己能不能装满别的杯子
				if (tmp.str[i] + tmp.str[j] - '0' >= glass[j]) { 
   
					string temp = tmp.str;
					int a = glass[j] - '0';
					int b = temp[j] - '0';
					temp[i] -= a - b;
					temp[j] = glass[j];
					if (s.find(temp) == s.end()) { 
   
						s.insert(temp);
						q.push(state(temp, k + 1));
					}
				}
			}
		}
	}
	return -1;
}

int main() { 
   
	int n1, n2, n3, n4;
	cin >> n1 >> n2 >> n3 >> n4;
	string str = to_string(n1) + to_string(n2) + to_string(n3) + to_string(n4);
	cout << bfs(str) << endl;
	return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/180090.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • mysql 通配符 替换,使用通配符替换的MySQL[通俗易懂]

    mysql 通配符 替换,使用通配符替换的MySQL[通俗易懂]I’mtryingtowriteaSQLupdatetoreplaceaspecificxmlnodewithanewstring:UPDATEtableSETConfiguration=REPLACE(Configuration,”%%ANY_VALUE%%””NEW_DATA”);SothatSDADASbecomesNEW_DATAIsthere…

    2022年7月16日
  • 网络基础知识题_基础有哪些类型

    网络基础知识题_基础有哪些类型本文结合多年来的工作实践,来详细讲述一下作为IT从业人员要掌握的一些基础网络知识。

    2022年9月3日
  • IIC通信协议详解

    IIC通信协议详解IIC通信协议详解IIC的概述IIC分为软件IIC和硬件IICIIC通信协议空闲状态开始信号与停止信号开始信号程序:IIC的概述IIC:两线式串行总线,它是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbs以上。时钟线SCL:在通信过程起到控制作用。数据线SDA:用来一位一位的传送数据。IIC分为软件IIC和硬件IIC软件IIC:软件IIC通信指的是用单片机的两个I/O端口模拟出来的IIC,用

    2022年6月10日
  • RocketMQ的长轮询消费方式

    RocketMQ的长轮询消费方式1.Push推送方式(即Server端推送消息给client):当Server收到消息发送者发送过来的消息后,Server端主动把消息推送给client,这个方式实时性比较好,但是增加了Server的工作负担,对Server的性能造成影响;另外Client如果不能够及时处理Server推送的消息,也是很大的问题。2.Pull拉取方式(即Client从Server拉取消息):Client…

    2022年6月24日
  • SpringBoot解决文件上传,返回可访问路径

    SpringBoot解决文件上传,返回可访问路径问题描述:SpringBoot项目中需要上传文件到当前服务器的磁盘(即物理地址),返回可访问的路径给前端。前端利用路径显示文件内容。开发环境:SpringBoot2.0以上、JDK1.81.在springboot中加入下面代码 @Value(“${file.uploadFolder}”) privateStringuploadFolder; @Bean MultipartConf…

    2022年5月2日
  • latex的参考文献写法标准_参考文献举例

    latex的参考文献写法标准_参考文献举例使用Latex撰写论文时,通常会遇到参考文献格式问题,下面我将与大家分享Latex参考文献规范写作。 1、建议使用bib文件编写Reference这样可以减少格式、空格和标点符号的错误。 Bibtex使用方法简介:新建一个空白文本文档,把后缀名改成bib即可,比如TIP.bib; 用TexWorks打开文件,加入你想要引用的文章,有一个简便的添加的方式是使用百度/谷歌…

    2022年9月4日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号