代码改变世界

poj 3414 Pots ----BFS 最短路和路径

2012-03-10 16:40  java环境变量  阅读(281)  评论(0编辑  收藏  举报

Pots
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6222   Accepted: 2614   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)

/*
   这道题 虽然AC了。但感觉很虚。。。 4172 kb。 16 ms。
   刚开始我以为情况很少,所以数组开得很小。
   交的时候WA了好几次,  直到把数组开到 1000000 才AC,
   心里一点底也没有 。。
  
  题目大意:  有两个固定容量 没有刻度的杯子,通过这两个杯子
  量出一定体积的水。
  输入 三个数 
  分别表示 1,2 两个杯子的容积,第三个数表示需要 量出的体积。

	这题的思路倒是不难,模拟六种操作,分六个方向扩散
   如果能找到结果,输出操作次数和操作。
   如果没有结果  输出 impossible。


  发现了些需要学习的东西,BFS怎么估算队列该开多大?
    希望各位朋友指点交流。
*/

//Memory: 4172 KB		Time: 16 MS
//Language: C++		Result: Accepted

#include<stdio.h>
#include<string.h>
void bfs(int x,int y);
int q[1000000][2],fa[1000000],dir[1000000],vir[2000],path[2000]; //数组大小怎么估算?
int a,b,c;
int main()
{
	while(scanf("%d%d%d",&a,&b,&c)!=EOF)
	{
		memset(vir,0,sizeof(vir));
		bfs(0,0);
	}
	return 0;
}

void bfs(int x,int y )
{
	int front=0,rear=0,i;
	q[rear][0]=x;
	q[rear++][1]=y;  // 队列每个元素有两个值  记录1,2两个盆的水的体积
	int m=x*a+y*b;   //我把两个盆中水的状态用 一维 存储
	fa[m]=m;
	vir[m]=1;  // 注意标记  不重复搜索相同的情况
	while(front<rear)
	{
		x=q[front][0];
		y=q[front++][1];  //元素出队
		m=x*a+y*b;   
		int nx,ny,z;
		for(i=0;i<6;i++)
		{
			// 分别考虑六个扩展的方向。
			if(i==0) nx=a,ny=y;
			if(i==1) nx=x,ny=b;
			if(i==2) nx=0,ny=y;
			if(i==3) nx=x,ny=0;
			if(i==4) {
			   if(y<=a-x) nx=x+y, ny=0;
			   else  nx=a, ny=y-(a-x);
			}
			if(i==5){
				if(x<=b-y) nx=0,ny=y+x;
				else nx=x-(b-y), ny=b;
			}
			z=nx*a+ny*b;
			if(!vir[z])  //如果是没有搜索的	情况
			{
			    vir[z]=1;  //标记已搜索
				q[rear][0]=nx;  
				q[rear++][1]=ny;  //新扩展点入队
				dir[z]=i;   //记下到这一步的方向
				fa[z]=m;     //记录父节点
			}
			if(nx==c||ny==c)   //找到目标
			{
				m=z;
				int tot=0,n=0;
				while(fa[m]!=m) //统计步数
				{
					tot++;
					path[n++]=dir[m];
					m=fa[m];
				}
				printf("%d\n",tot);
				for(n=n-1;n>=0;n--)  //输出路径
				{
					if(path[n]==0) printf("FILL(1)\n");
					if(path[n]==1) printf("FILL(2)\n");
					if(path[n]==2) printf("DROP(1)\n");
					if(path[n]==3) printf("DROP(2)\n");
					if(path[n]==4) printf("POUR(2,1)\n");
					if(path[n]==5) printf("POUR(1,2)\n");
				}
				return ;
			}
		}
	}
	printf("impossible\n");   //搜索失败 
}