1. 程式人生 > >Pots(BFS+路徑記錄)

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;
}