B - Pour Water倒水问题

题目:

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

putfill 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)程序来判定你写的代码是否正确。

题目分析:

此题为倒水问题,有A,B两个杯子,要倒出容量为C的水,大方面来讲有三种情况,即一个杯子倒空,一个杯子倒满以及从一个杯子倒入另一个杯子中;而细分来讲有八种情况,分别为:
(1)倒空A杯。
(2)倒空B杯。
(3)倒满A杯。
(4)倒满B杯。
(5)当A杯不满且B杯有水的情况,B杯水倒入A杯:
(5.1)A.B水量不大于A杯容量时,倒入后B杯水为0,A杯为A+B的水量。
(5.2)A.B水量大于A杯容量时,倒入后B杯水为A+B的水量减去A的容量,A杯为A的容量。
(6)当B杯不满且A杯有水的情况,A杯水倒入B杯:
(6.1)A.B水量不大于B杯容量时,倒入后A杯水为0,B杯为A+B的水量。
(6.2)A.B水量大于B杯容量时,倒入后A杯水为A+B的水量减去A的容量,B杯为B的容量。

要找出可行的方案,可以采用bfs宽度搜索,亦可以采用dfs深度搜索,此处采用bfs,因为bfs可以找到步骤最少的方案。
首先将每个状态的A,B的水量用结构体node表示,其中node结构体中的status表示该A,B状态是经过什么操作形成的。然后定义一个队列,当队列不为空时,取出队首元素,根据前面分析的倒水的八种情况,将可能的A,B水量情况压入队列之中直到A,B中至少有一个水量刚好等于目标水量C。最后递归输出达到目标水量进行步骤的status即可。

代码:

#include<iostream>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<map>
using namespace std;
const int maxn=1e3+5;
struct node
{
    int A;
    int B;
    int status; 
    bool operator<(const node &s) const
    {
        return A!=s.A ? A<s.A : B<s.B ;
    }
    bool operator==(const node &s) const 
    {
        return A == s.A && B == s.B;
    }
};
bool vis[maxn][maxn];
node pre[maxn][maxn];
void trans(node tt)
{
    switch(tt.status)
    {
       case 1:
	   cout<<"fill B"<<endl;
	   break;
       case 2:
	   cout<<"empty B"<<endl;
	   break;
       case 3:
	   cout<<"fill A"<<endl;
	   break;
       case 4:
	   cout<<"empty A"<<endl;
	   break;
       case 5:
	   cout<<"pour A B"<<endl;
	   break;
       case 6:
	   cout<<"pour B A"<<endl;
	   break;
       default:
	   break;  
     }
}
void output(node tt)
{
      if(tt.A!=0||tt.B!=0)
      {
	       output(pre[tt.A][tt.B]); 
	       trans(tt); 
      }
} 
void bfs(int a,int b,int c)
{
     queue<node> q;//队列 
     node s;
     node t;
     memset(vis,false,sizeof(vis));
     memset(pre,0,sizeof(pre));
     s.A=s.B=0;//起点两杯水均为空
     vis[s.A][s.B]=true;
     q.push(s);
     while(!q.empty())
     { 
		  s=q.front();
		  q.pop();
		  if(s.A==c||s.B==c)//完成 
		  {
			   output(s);
			   cout<<"success"<<endl; 
			   return ;
		  }
		  if(s.B<b)//b中水不满,倒满B杯中的水 
		  {
				t.B=b;
				t.A=s.A;
				if(!vis[t.A][t.B])
				{
			      	  t.status=1;
				      q.push(t);
				      vis[t.A][t.B]=true;
				      pre[t.A][t.B]=s;
				}
		  }
		  if(s.B>0)//b中有水,倒空B杯中的水 
		  {
				 t.B=0;
				 t.A=s.A;
				 if(!vis[t.A][t.B])
				 {
				      t.status=2;
				      q.push(t);
				      vis[t.A][t.B]=true;
			          pre[t.A][t.B]=s; 
		         } 
		  }
          if(s.A<a)//a中水不满,倒满A杯中的水 
		  {
			      t.A=a;
		          t.B=s.B; 
		          if(!vis[t.A][t.B])
		          {
		               t.status=3;
		               q.push(t);
		               vis[t.A][t.B]=true;
		               pre[t.A][t.B]=s;
		           }
	       }
		  if(s.A>0)//a中有水,倒空a杯中的水 
	      {
		        t.A=0;
		        t.B=s.B;
		        if(!vis[t.A][t.B])
		        {
		              t.status=4;
		              q.push(t);
		              vis[t.A][t.B]=true;
		              pre[t.A][t.B]=s;
		         } 
		  }
		  if(s.A!=0&&s.B<b)//a中有水且b中水不满,考虑a杯倒入b杯 
		  {
		        if(s.A+s.B<=b)
		        {
		             t.B=s.A+s.B;
		             t.A=0;
		             if(!vis[t.A][t.B])
		             {
		                  t.status=5;
		                  q.push(t);
		                  vis[t.A][t.B]=true;
		                  pre[t.A][t.B]=s;
		              }
		         }
				 else
				 {
				      t.B=b;
				      t.A=s.B+s.A-b;
				      if(!vis[t.A][t.B])
				      {
				          t.status=5;
				          q.push(t);
				          vis[t.A][t.B]=true;
				          pre[t.A][t.B]=s;
				       }
			  	  } 
		   } 
          if(s.B!=0&&s.A<a)//a中有水且b中水不满,考虑b杯倒入a杯 
          {
				 if(s.A+s.B<=a)
				 {
				      t.A=s.A+s.B;
				      t.B=0;
				      if(!vis[t.A][t.B])
				      {
				           t.status=6;
				           q.push(t);
				           vis[t.A][t.B]=true;
				           pre[t.A][t.B]=s;
				       }
				 }
				 else
				 {
				       t.A=a;
				       t.B=s.B+s.A-a;
				       if(!vis[t.A][t.B])
				       {
				            t.status=6;
				            q.push(t);
				            vis[t.A][t.B]=true;
				            pre[t.A][t.B]=s;
				       }
			     } 
	        } 
      } 
}
int main()
{
     int aa,bb,cc;
     while(cin>>aa>>bb>>cc)
     {
         bfs(aa,bb,cc);
     }
     return 0;
}

样例运行:

在这里插入图片描述

发布了15 篇原创文章 · 获赞 0 · 访问量 808

猜你喜欢

转载自blog.csdn.net/qq_43746837/article/details/104592038
今日推荐