码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-04-09 08:53:22      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:acm   搜索   

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

下面是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;
}

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

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

标签:acm   搜索   

原文地址:http://blog.csdn.net/qq_25425023/article/details/44948069

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!