Pots(BFS+路径记录)

023:Pots

总时间限制: 

1000ms

内存限制: 

65536kB

描述

You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:

  1. FILL(i)        fill the pot i (1 ≤ ≤ 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).

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.

输入

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

输出

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’.

样例输入

3 5 4

样例输出

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

分析:如果不是放在广搜的专题里,根本就不知道一个用广搜(开始自闭),题目说的是有两个水桶x,y容量分别是a,b,你用每个桶三种共六种操作,然后就是用着六种操作配出c容量的水。当然其中要用vis[x][y]记录每个状态,所有状态都记录完了还是的不出c容量的水,那说明配不出来。

#include <stdio.h>
#include <string.h>
#include <queue>
#include <stack>
#include <iostream>
using namespace std;

struct cup{
	int x,y;//两个杯子的水容量的状态 
	int step;//这是第几步操作 
	int flag;//标记操作的代号 
	cup *pre;//记录该状态的前驱结点 
};
queue<cup> Q;//用于装每一次的状态,并且队列为结构体类型 
stack<int> R;//用于从头到尾输出操作的代号 
int a,b,e;//三个容量 
int vis[110][110]={0};
int ans;
void BFS(int x,int y)
{
	int i;
	cup c;//杯子的当前的状态 
	cup t[310];//用于存放每一次目前瓶子里剩水的量 
	c.x=0,c.y=0;//此时两个杯中还没有水 
	c.flag=0;//表示还没有操作 
	c.pre=NULL;//当前状态的前一个状态为空 
	c.step=0;//当前操作的步数 
	Q.push(c);//c入列 
	vis[x][y]=1;//当前两个杯子的状态记录为1 
	int count=-1;//为step的前一个 
	while(!Q.empty()){
		count++;
		t[count]=Q.front();
		Q.pop();
		for(i=1;i<=6;i++){
			switch(i)
			{
				case 1://fill(a) 
					c.x=a;
					c.y=t[count].y;
					c.flag=1;
					break;
				case 2://fill(b)
					c.x=t[count].x;
					c.y=b;
					c.flag=2;
					break;
				case 3://drop(a)
					c.x=0;
					c.y=t[count].y;
					c.flag=3;
					break;
				case 4://drop(b)
					c.x=t[count].x;
					c.y=0;
					c.flag=4;
					break;
				case 5://pour(x,y)
					if(t[count].x>b-t[count].y){//x中还有剩的,y满 
						c.x=t[count].x-(b-t[count].y);
						c.y=b;
					}
					else{//x中没有剩 
						c.x=0;
						c.y=t[count].y+t[count].x;
					}
					c.flag=5;
					break;
				case 6://pour(y,x)
					if(t[count].y>a-t[count].x){//y中还有剩,x满 
						c.y=t[count].y-(a-t[count].x);
						c.x=a;
					}
					else{//y中没有剩 
						c.y=0;
						c.x=t[count].y+t[count].x;
					}
					c.flag=6;
					break;
				
			}
			if(vis[c.x][c.y]){//如果两个杯子的状态已经存在过了,就continue 
				continue;
			}
			vis[c.x][c.y]=1;//没有就记录该状态 
			c.step=t[count].step+1;//步数加1 
			c.pre=&t[count];//记录步数的前驱结点 
			if(c.x==e||c.y==e){//如果其中一个杯子达到要求的容量e,则结束 
				ans=c.step;//记录步数 
				while(c.pre){//当前去结点不为NULL时,就进入 
					R.push(c.flag);//把存在的代号放入堆栈 
					c=*c.pre;//当把c的前驱结点赋给c 
				}
				return;//退出 
			}
			Q.push(c);//如果没发生if,就把下一个杯子的状态c入列 
		}
	}
} 
void print()
{
	while(!R.empty()){
		int i=R.top();//类似于Q.front,都是标记处顶部的位置 
		R.pop();
		switch(i)
		{
			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;
		}
	}
}

int main()
{
	cin>>a>>b>>e;
	BFS(0,0);
	if(ans==0){//所有状态都走过了,还是没有找到可以得出e容量状态的水杯 
		cout<<"impossible"<<endl;
	}
	else{
		cout<<ans<<endl;
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42105789/article/details/84495143
今日推荐