南阳理工--21--三个水杯~~广度优先搜索

这一题运用广度优先搜索可以解决,主要是各个状态的转移以及某个状态出现过要标记,避免重复,进入死循环。

下面是AC代码,上面有详细的讲解:

# include <iostream>
# include <cstring>
# include <queue>
using namespace std;

class data                   //队列的结点,
{
public:
	int water[3];            //三个水杯的状态
	int step;                //步骤
};
bool visited[100][100][100]; //标记三个水杯的状态,避免重复
int start[3], end[3];        //输入的开始状态和结束状态

int main()
{
	int BFS();
	int n;
	cin >> n;
	while(n--)
	{
		cin >> start[0] >> start[1] >> start[2];
		cin >> end[0] >> end[1] >> end[2];
		int k = BFS();
		cout << k << endl;
	}
	return 0;
}

int Achieve(data node)         //判断是否到达结束状态
{
	for(int i = 0; i < 3; i++)
	{
		if(node.water[i] != end[i])
			return 0;
	}
	return 1;
}

int BFS()               //广度优先搜索
{
	int i, j;
	queue <data> Que;   //创建队列
	memset(visited, false, sizeof(visited));  //初始化visited数组
	data s1;                                 //开始结点
	s1.water[0] = start[0];                  //第一个杯子
	s1.water[1] = 0;                         //第二个杯子
	s1.water[2] = 0;                         //第三个杯子
	s1.step = 0;                             //步数
	Que.push(s1);                            //进队列
	visited[start[0]][0][0] = true;          //标记该状态出现过
	while(!Que.empty())                      //判断队列是否为空
	{
		s1 = Que.front();                    //从队列中获取队头
		Que.pop();
		if(Achieve(s1))                     //到达结束状态,返回步数
			return s1.step;
		for(i = 0; i < 3; i++)              //从i号杯子到往另外两个杯子中放水。
		{                                   //i为倒水的杯子,j为接水的杯子
			for(j = 0; j < 3; j++)
			{
				if(j == i)                  //i=j,杯子相同,只能往另外的杯子倒水
					continue;
				if(s1.water[i] != 0 && s1.water[j] < start[j])  //倒水的杯子必须有水且接水的杯子水量不能超过容量
				{
					data node;
					node = s1;
					int pour = start[j] - node.water[j];       //要倒的水量
					if(node.water[i] >= pour)                  //倒水的杯子的水量大于等于pour,倒水的杯子不会倒空
					{
						node.water[j] += pour;
						node.water[i] -= pour;
					}
					else                                        //倒空的情况
					{
						node.water[j] += node.water[i];
						node.water[i] = 0;
					}
					node.step = s1.step + 1;                     //步数加一
					if(!visited[node.water[0]][node.water[1]][node.water[2]])  //判断该状态是否出现过
					{
						visited[node.water[0]][node.water[1]][node.water[2]] = true;
						Que.push(node);
					}
				}
			}
		}
	}
	return -1;                                         //不能实现,返回-1;
}

很容易看得懂的,慢慢理解,细细体会。

时间: 2024-10-13 02:01:39

南阳理工--21--三个水杯~~广度优先搜索的相关文章

NYOJ 21 三个水杯 【暴力+BFS】

题意:不解释. 策略:广搜. 解释一下为什么会是广搜,一个水杯只能向其他两个水杯倒水,不能向他自己倒水,这样一共有三个水杯也就是有6种情况,只需要一步一步的搜索就好了(数据没多大 <100), 我们将每一次出现的水杯中的水数(就是有多少水)都标记下来,如果是以前没有出现过,那么就进队列,同时将此时的水杯数标记下来,说明该种情况已出现,一直找到想要找的状态为止,如果都找不到,就返回-1. 难点:我在下面的代码中会有详细的解释. ps:网上有说这道题是隐式图,因为BFS原来是来搜索图的,我比较认可.

Nyoj 21 三个水杯(bfs)

三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算.现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数. 输入 第一行一个整数N(0<N<50)表示N组测试数据接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的

nyoj 21 三个水杯

三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算.现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数. 输入 第一行一个整数N(0<N<50)表示N组测试数据接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的

队列,广搜 nyoj 21 三个水杯

三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算.现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数. 输入 第一行一个整数N(0<N<50)表示N组测试数据 接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯

BFS [NYOJ 21] 三个水杯

三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算.现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数. 输入 第一行一个整数N(0<N<50)表示N组测试数据接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的

图论(三)------广度优先搜索与单源无权最短路径

有一个无权的图G,使用某个顶点s作为输入参数,找出从s到其它顶点的最短路径.这样,只要计算包含在路径中的边数就可以了. 比如,一个word ladder problem,一次只变换一个字母,找出从fool到sage的最短路径. 可用的单词可以转化为一个图: 首先寻找与fool距离为1的顶点: 然后可以寻找距离fool为2的顶点: 最后,搜索出全部顶点: 这样搜索一个图的方法称为广度优先搜索:距开始点最近的那些顶点首先被搜索,最远的那些顶点最后被搜索. def unweighted(G,v): q

基础算法(三)——广度优先搜索

广度优先搜索(Breadth First Search),是很多重要的图的算法的原型. 重要的作用:遍历.对于图的遍历,一般有以下的基本思想: ①从图中某个顶点V0出发,并访问此顶点: ②从V0出发,访问V0的各个未曾访问的邻接点W1,W2,-,Wk;然后,依此从W1,W2,-,Wk 出发访问各自未被访问的邻接点. ③重复②,直到全部顶点都被访问为止. [例]如图1-7,按照广度优先搜索的思想遍历这张图. 正确的方法应该是: [例]编写"连连看"的简单程序 规则是:相连不超过两个弯的相

NYOJ21 三个水杯 (经典问题 bfs)

题目描述: http://acm.nyist.net/JudgeOnline/problem.php?pid=21 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算.现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数. 输入 第一行一个整数N(0<N<50)表示N组测试数据 接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100

SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Description 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) Input 输入第一行为整数n(0< n <100),表示数据的组数.对于每组数据,第一行是三个整数k,m,t(0<