寒假训练补题-第四天-G-7-倒水类问题BPS

原题链接:http://poj.org/problem?id=3414
Description
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:

描述
你有两个罐子,分别有A和B升的体积。
可以执行以下操作:

1.FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
2.DROP(i) empty the pot i to the drain;
3.POUR(i,j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).

1.FIll(i)从水龙头填充罐i(1≤i≤2);
2.DROP(i)把锅子倒到排水管里;
3.POUR(i,j)从锅i倒入锅j;在此操作之后,罐j已满(并且罐i中可能存在一些水),或罐i是空的(并且其所有内容已被移动到罐j)。

Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.

编写一个程序来找到这些操作的最短可能序列,这些操作将在其中一个罐中产生完全C升的水。

Input
On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).

输入
在第一行和唯一行上是数字A,B和C.这些都是1到100之间的整数,并且C≤max(A,B)。

Output
The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.

产量
输出的第一行必须包含操作序列K的长度。以下K行必须各自描述一个操作。
如果有几个最小长度的序列,则输出其中任何一个。
如果无法实现所需的结果,则文件的第一行和唯一行必须包含“impossible”一词。

Sample Input
3 5 4

Sample Output
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)

个人心得:倒水里面的经典例子了,BFS实现,套模板,后面回溯一下步骤
ac代码:

#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include
using namespace std;

int f[105][105];    //用来标记当前状态是否已经有过
int A, B, C;
struct node   //定义结构体
{
	int a, b;//两个容器中的水 
	int sa, sb;//上个状态 
	int way;  //  操作1到6 
	int step;  // 当前步数 
}lu[105][105];   //用来保存操作

queue que;       //声明que是一个node型的一个队列

void print(int a, int b)     //利用回溯输出
{
	if (lu[a][b].a == 0 && lu[a][b].b == 0) //到达初始状态结束
		return;
	print(lu[a][b].sa, lu[a][b].sb);
	switch (lu[a][b].way)
	{
	case 1: cout << "FILL(1)" << endl; break;
	case 2: cout << "FILL(2)" << endl; break;
	case 3: cout << "DROP(1)" << endl; break;
	case 4: cout << "DROP(2)" << endl; break;
	case 5: cout << "POUR(1,2)" << endl; break;
	case 6: cout << "POUR(2,1)" << endl; break;
	}
}

void push(node d) //入队操作
{
	if (f[d.a][d.b] == 0)
	{
		que.push(d);         //在队列que的末尾插入d
		lu[d.a][d.b] = d;    //把d的值赋给
		f[d.a][d.b] = 1;
	}
}
void bfs()
{
	/*while(!que.empty())
	 que.pop();      */
	que.push(lu[0][0]);   //将第一个点入队
	while (!que.empty())   //队列非空
	{
		node u = que.front();  //取队首元素
		que.pop();           //将队首元素出队
		if (u.a == C || u.b == C)      //如果两个壶中有一个满足条件则输出,结束bfs
		{
			cout << u.step << endl;
			print(u.a, u.b);
			return;
		}

		node v;        //辅助点
		v.sa = u.a;      //赋值
		v.sb = u.b;
		v.step = u.step + 1;
		if (u.a != A)  //1. 加满1 
		{
			v.a = A;
			v.b = u.b;
			v.way = 1;
			push(v);
		}

		if (u.b != B) //2. 加满2
		{
			v.a = u.a;
			v.b = B;
			v.way = 2;
			push(v);
		}

		if (u.a != 0) //3.倒光1 
		{
			v.a = 0;
			v.b = u.b;
			v.way = 3;
			push(v);
		}

		if (u.b != 0) //4.倒光2 
		{
			v.a = u.a;
			v.b = 0;
			v.way = 4;
			push(v);
		}

		if (u.a != 0 && u.b != B)//5. 把1到给2 
		{
			if (u.a + u.b >= B)
			{
				v.b = B;
				v.a = u.a + u.b - B;
			}

			else
			{
				v.a = 0;
				v.b = u.a + u.b;
			}
			v.way = 5;
			push(v);
		}
		if (u.b != 0 && u.a != A)//6. 把2到给1 
		{
			if (u.a + u.b >= A)
			{
				v.a = A;
				v.b = u.a + u.b - A;
			}
			else
			{
				v.a = u.a + u.b;
				v.b = 0;
			}
			v.way = 6;
			push(v);
		}
	}
	cout << "impossible" << endl;
}

int main()
{
	memset(f, 0, sizeof(f));
	lu[0][0].a = lu[0][0].b = 0;
	lu[0][0].sa = lu[0][0].sb = -1;
	lu[0][0].step = 0;
	f[0][0] = 1;
	cin >> A >> B >> C;
	bfs();
	return 0;
}

你可能感兴趣的:(acm)