1. 程式人生 > >POJ3414 Pots【BFS】

POJ3414 Pots【BFS】

Pots

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 23177   Accepted: 9827   Special Judge

Description

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.

Input

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

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

Sample Input

3 5 4

Sample Output

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

Source

Northeastern Europe 2002, Western Subregion

題目連結:POJ3414 Pots

問題描述:給你兩個空壺,容量分別為A,B。定義3中操作,FILL(i)表示把壺i裝滿,DROP(i)表示把壺清空,POUR(i,j)表示把壺i中的水倒入j中,直到i變空,或者j變滿。問經過若干步操作後,是否能使得其中一個壺的容量為C,如果可以則列印步數和相應步驟,否則輸出“impossible

題解:初始狀態為把壺a裝滿或者把壺b裝滿,然後對每個狀態進行6中操作:裝滿壺a,轉滿壺b,清空壺a,清空壺b,壺a倒入壺b,壺b倒入壺a,詳情如下

AC的C++程式:

#include<iostream>
#include<queue>
#include<string>
#include<cstring>
#define MIN(x,y) x<y?x:y
using namespace std;
const int N=500;
struct Node{
	int a,b,pre,id;
	string s;
}st[2*N];

int A,B,C;
bool vis[N][N];

int bfs()
{
	memset(vis,false,sizeof(vis));
	queue<Node>q;
	//初始有兩個狀態,要麼把a裝滿,要麼把b裝滿 
	st[0].a=A,st[0].b=0,st[0].pre=-1,st[0].id=0,st[0].s="FILL(1)";
	st[1].a=0,st[1].b=B,st[1].pre=-1,st[1].id=1,st[1].s="FILL(2)";
	q.push(st[0]);
	q.push(st[1]);
	vis[A][0]=vis[0][B]=true;
	int k=2;
	while(!q.empty()){
		Node f=q.front();
		q.pop();
		if(f.a==C||f.b==C)//如果轉換成功,返回此狀態的編號 
		  return f.id;
		//FILL操作
		Node e=f;
		if(e.a!=A&&!vis[A][e.b]){
			e.a=A,e.id=k,e.pre=f.id,e.s="FILL(1)";
			st[k++]=e; 
			vis[A][e.b]=true;
			q.push(e);
		}
		e=f;
		if(e.b!=B&&!vis[e.a][B]){
			e.b=B,e.id=k,e.pre=f.id,e.s="FILL(2)";
			st[k++]=e; 
			vis[e.a][B]=true;
			q.push(e);
		}
		//DROP操作
		e=f;
		if(e.a!=0&&!vis[0][e.b]){
			e.a=0,e.id=k,e.pre=f.id,e.s="DROP(1)";
			st[k++]=e; 
			vis[0][e.b]=true;
			q.push(e);
		}
		e=f;
		if(e.b!=0&&!vis[e.a][0]){
			e.b=0,e.id=k,e.pre=f.id,e.s="DROP(2)";
			st[k++]=e; 
			vis[e.a][0]=true;
			q.push(e);
		}
		//POUR操作
		e=f;
		if(e.a!=0){
			int d=MIN(e.a,B-e.b);//a向b中倒水的最大量 
			if(!vis[e.a-d][e.b+d]){
				vis[e.a-d][e.b+d]=true;
				e.a-=d,e.b+=d,e.pre=f.id,e.id=k,e.s="POUR(1,2)";
				st[k++]=e;
				q.push(e);
			}
		}
		e=f;
		if(e.b!=0){
			int d=MIN(A-e.a,e.b);//b向a中倒水的最大量 
			if(!vis[e.a+d][e.b-d]){
				vis[e.a+d][e.b-d]=true;
				e.a+=d,e.b-=d,e.pre=f.id,e.id=k,e.s="POUR(2,1)";
				st[k++]=e;
				q.push(e);
			}
		}
	}
	return -1; //表示不能成功 
}
void print(int i)
{
	if(st[i].pre!=-1)
	  print(st[i].pre);
	cout<<st[i].s<<endl;
}

int main()
{
	scanf("%d%d%d",&A,&B,&C);
	if(C==0){
		printf("0\n");
		return 0;
	}
	int id=bfs();//終止狀態id
	if(id==-1){
		printf("impossible\n");
		return 0;
	}
	int cnt=1,i=id;
	while(st[i].pre!=-1){
		i=st[i].pre;
		cnt++;
	}
	printf("%d\n",cnt);
	print(id);
	return 0;
}