倒水问题(搜索)

倒水问题
“fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空。
Input
输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质。
Output
你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。
Sample Input
2 7 5
2 7 4
Sample Output
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success

解题思路
倒水问题的解法有很多,但接下来探讨的是利用广度优先搜索算法去解决问题。其实我最开始看题想到的是来自离散数学里的例子——人、狼、羊、菜过河问题(大家感兴趣可以自己查阅),去建立不同河岸状态的关系图,哪两种状态之间可以互相转换。倒水为题也是这样,他的状态之间的转换方式有6中,fill A,fill B,pour A B,pour B A,empty A,empty B。遍历的就是杯子里所装水的状态,想清楚这些bfs就很好实现了。(注意答案不唯一)

#include<stdio.h>
#include<queue>
#include<vector>
using namespace std;
struct cup//记录状态结构体
{
	int A, B;//容量为A,B罐子水含量
	cup(const int& _A,const int& _B):
		A(_A),B(_B){}
};
int ab[1001][1001],pre[1001][1001];
//数组ab存有什么状态转移过来,pre存有什么方式转移过来的
void Print(int &x, int &y, int &B)//输出
{
	int a = x, b = y;
	vector<int>ans;
	while (ab[a][b] != a * B + a + b)
	{
		int ta = ab[a][b] / (B + 1), tb = ab[a][b] % (B + 1);
		ans.push_back(pre[a][b]);
		a = ta; b = tb;
	}
	for(int i=ans.size()-1;i>=0;i--)
		switch (ans[i])
		{
			case 0:
				printf("fill A\n");
				break;
			case 1:
				printf("fill B\n");
				break;
			case 2:
				printf("pour A B\n");
				break;
			case 3:
				printf("pour B A\n");
				break;
			case 4:
				printf("empty A\n");
				break;
		default:
			printf("empty B\n");
			break;
		}
	printf("success\n");
}
void bfs(int& A, int& B, int& C)//广度优先搜索
{	
	queue<cup>q;
	q.push(cup(0, 0));
	for(int i=0;i<=A;i++)
		for(int j=0;j<=B;j++)
			ab[i][j]=-1; 
	ab[0][0] = 0;
	while (!q.empty())
	{
		cup now = q.front();
		q.pop();
		int a = now.A, b = now.B;
		for (int i = 0; i < 6; i++)
		{
			int x=-1, y=-1;
			if (0 == i && a < A && -1 == ab[A][b])
			{
				x = A; y = b;
			}
			if (1 == i && b < B && -1 == ab[a][B])
			{
				x = a; y = B;
			}
			if (2 == i && b < B && a>0)
			{
				if (a > B - b && -1==ab[a-B+b][B])
				{
					x = a - B + b; y = B;
				}
				if (a < B - b && -1 == ab[0][b + a])
				{
					x = 0; y = b + a;
				}
			}
			if (3 == i && a < A && b>0)
			{
				if (b > A - a && -1 == ab[A][b-A+a])
				{
					y = b - A + a; x = A;
				}
				if (b < A - a && -1 == ab[b+a][0])
				{
					y = 0; x = b + a;
				}
			}
		if (4 == i && -1 == ab[0][b])
			{
				x = 0; y = b;
			}
			if (5 == i && -1 == ab[a][0])
			{
				x = a; y = 0;
			}

			if (x != -1 && y != -1)
			{
				pre[x][y] = i;
				ab[x][y] = a * B + a + b;
				if (x == C || y == C)//罐子中包含C单位的水,结束搜索
				{
					Print(x, y, B);
					return;
				}	
				q.push(cup(x, y));
			}
		}
	}
}
int main()
{
	int A, B, C;
	while (scanf("%d%d%d", &A, &B, &C) != EOF)
		if (0 == C)printf("success\n");
		else bfs(A,B,C);
	return 0;
}
发布了19 篇原创文章 · 获赞 0 · 访问量 518

猜你喜欢

转载自blog.csdn.net/YingMila/article/details/104660560