B - Pour Water || BFS

倒水问题 “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

Notes
如果你的输出与Sample Output不同,那没关系。对于某个"A B C"本题的答案是多解的,不能通过标准的文本对比来判定你程序的正确与否。 所以本题由 SPJ(Special Judge)程序来判定你写的代码是否正确。

解题思路
用BFS来实现,并且每一步都记录上一步的状态,并且利用vis数组来判断是否走过该状态,并且利用vis数组中的数字来记录该状态是怎么产生的。

代码实现

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

int vis[2000][2000];   //vis =不同的值对应不同的操作

struct P{
	int A,B;
};

queue< P >  q;

P SS[2000][2000]; //记录上一个状态 

P bfs(int x,int y,int z)  //x,y是杯子的容量 
{
	vis[0][0] = -1;  //一开始2个都是空的 
	P a ;
	SS[0][0].A = -1,SS[0][0].B=-1;  //最开始的状态是没有上一个状态的,所以-1
	a.A = 0,a.B = 0;   //因为一开始是0, 0状态
	q.push(a); 
	int a1,b1;
	P  ss;
	while( !q.empty() )
	{
	ss = q.front();
	a1 = ss.A;
	b1 = ss.B;
	q.pop();
	for(int i=0;i<6;i++)  //6种操作
	{
		if( i==0 )   //倒满A 
		{
			if( vis[x][b1] == 0 )
			{
				vis[x][b1] =1;
				P s1;
				s1.A = x;
				s1.B = b1;
				SS[s1.A][s1.B].A = a1;  //记录上一个状态
				SS[s1.A][s1.B].B = b1;
				if(s1.A == z || s1.B == z)
				return s1;
				q.push(s1);
			}
		}
		else if(i==1) //倒满B 
		{
			if(vis[a1][y] == 0)
			{
				vis[a1][y] =2;
				P s2 ;
				s2.A =a1;
				s2.B =y;
				SS[s2.A][s2.B].A = a1;
				SS[s2.A][s2.B].B = b1;
				if(s2.A==z || s2.B==z)
				return s2;
				q.push(s2);
			}
		}
		else if(i==2) //A->B 
		{
			P  s3;
			if( b1 < y) //b 不满 
			{
				int b2 = y-b1;
				if( a1 >= b2)  //如果A有b2那么多来倒 
				{
					int a2 =  a1-b2;
					s3.A = a2;
					s3.B = y;
					if( vis[s3.A][s3.B] == 0)
					    {
						
						vis[s3.A][s3.B] =3;
						SS[s3.A][s3.B].A = a1;
						SS[s3.A][s3.B].B = b1;
						if(s3.A==z || s3.B==z)
						return s3;
						q.push(s3);
						}
				}
				else //A没有b2那么多
				{
					s3.A = 0;
					s3.B = b1 + a1;
					if( vis[s3.A][s3.B] ==0)
					    {
						
						vis[s3.A][s3.B] =3;
						SS[s3.A][s3.B].A = a1;
						SS[s3.A][s3.B].B = b1;
						if(s3.A==z || s3.B==z)
						return s3;
						q.push(s3);
						}
				 } 
			}
			
		}
		else if(i==3) //b->A
		{
			P s4;
			
			if( a1 < x )//A不满
			{
				int  a2 = x-a1; //装满A要的水 
				if( a2 > b1 )  //如果b的水灌不满A
				{
					s4.A = a1+b1;
					s4.B = 0;
					if( vis[s4.A][s4.B] ==0)
					    {
						
						vis[s4.A][s4.B] =4;
						SS[s4.A][s4.B].A = a1;
						SS[s4.A][s4.B].B = b1;
						if(s4.A==z || s4.B==z)
						return s4;
						q.push(s4);
						}
				 } 
				else
				{
					s4.A = x;
					s4.B = b1 - a2;
					if( vis[s4.A][s4.B] == 0)
					    {
						
						vis[s4.A][s4.B] =4;
						SS[s4.A][s4.B].A = a1;
						SS[s4.A][s4.B].B = b1;
						if(s4.A==z || s4.B==z)
						return s4;
						q.push(s4);
						}				
									}
				
			 } 
		
		}
		else if(i==4) //A->0
		{
			P s3;
			s3.A = 0;
			s3.B = b1;
			if( vis[s3.A][s3.B] ==0)
					    {
					
						vis[s3.A][s3.B] =5;
						SS[s3.A][s3.B].A = a1;
						SS[s3.A][s3.B].B = b1;
						if(s3.A==z || s3.B==z)
						return s3;
						q.push(s3);
						}
		}
		else if(i==5) //B->0
		{
			P s3;
			s3.A = a1;
			s3.B = 0;
			if( vis[s3.A][s3.B] == 0)
					    {
						q.push(s3);
						vis[s3.A][s3.B] =6;
						SS[s3.A][s3.B].A = a1;
						SS[s3.A][s3.B].B = b1;
						if(s3.A==z || s3.B==z)
						return s3;
						}
		}
	}
  }
}

int main()
{
	int A,B,C;

	P pp[1001]; //用来提取状态的 
	
	while(cin>>A>>B>>C)
	{
		if( A>0 && B>=A && B>=C && B<=1000 )
		{
		
		//cout<< " **** "<<endl; 
		while (!q.empty()) 
			q.pop();
		
		P ppp= bfs(A,B,C);
		int pi=0;
		
		while( ppp.A!=-1 &&  ppp.B!=-1 ) //将过程提取出来到pp中
		{
			pp[pi] = ppp;
		//	cout<<pp[pi].A<<" "<<pp[pi].B<<endl;
			ppp = SS[ppp.A][ppp.B];
			
			pi++;
			
		}
	//	cout<<"pi="<<pi<<endl;
		for(int i=pi-1;i>=0;i--)   //利用vis中值的不同来输出操作
		{
			//cout<<"**"<<endl;
		//	cout<< pp[i].A<<" "<<pp[i].B;
			int v = vis[pp[i].A ][pp[i].B];
		//	cout<<" v= "<<v;
			if( v == 1 )
				cout<<"fill A"<<endl;
			else if(v == 2)
				cout<<"fill B"<<endl;
			else if(v == 3)
				cout<<"pour A B"<<endl;
			else if(v==4)
				cout<<"pour B A"<<endl;
			else if(v==5)
				cout<<"empty A"<<endl;
			else if(v==6)
				cout<<"empty B"<<endl;
		}
		cout<<"success"<<endl;
	}
	}
	return 0;
 } 

收获
实现bfs,并要求记录过程的这种题目,我们可以使用vis数组进行判断,甚至还可以利用vis数组来记录进行了什么操作。

发布了32 篇原创文章 · 获赞 1 · 访问量 1063

猜你喜欢

转载自blog.csdn.net/Hanpi_learnc/article/details/104619934
今日推荐