Pots
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 22868 | Accepted: 9707 | Special Judge |
Description
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
- FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
- DROP(i) empty the pot i to the drain;
- 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 A, B, 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
题意:
有两个桶,容量分别为a和b。最初状态下,两个桶并没有放水。
现在有三个操作 1: DROP i 将i桶内的水全部倒掉
2:FILL i 将i桶装满水
3:POUR(I,J) 将j桶内的水倒入i中,即将溢出时停止倒水。(不会有水的损耗)
问你再最少在第几步操作时,其中一个桶内的水为C,并输出操作步骤
两个桶内的水可看为(x,y) 即可以看成是平面上的一个点,从而记录访问情况。
这里用path数组记录每一个操作的上一个操作的坐标。从而实现路径记录,输出时反向输出即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
using namespace std;
#define LL long long
#define M(a,b) memset(a,b,sizeof(a))
const int MAXN = 1e3+5;
const int INF = 0x3f3f3f3f;
int a,b,c;
int len;
struct Node
{
char c;///记录操作类型
int i,j;
int from;///记录上一个操作的下标
} path[MAXN];///记录路径
int vis[MAXN][MAXN];///记录点的访问情况
queue<pair<pair<int,int>,int> >q;
int bfs(int x,int y)
{
vis[x][y] = 1;
q.push(make_pair(make_pair(x,y),len));///len代表现在此操作的下标
while(!q.empty())
{
int x1 = q.front().first.first;
int y1 = q.front().first.second;
int temp = q.front().second;
//printf("x==%d y==%d\n",x1,y1);
if(x1==c||y1==c)
{
return temp;
}
q.pop();
if(vis[x1][0]==0)///DROP操作
{
vis[x1][0] = 1;
len ++;
path[len].c ='D';
path[len].i = 2;
path[len].from = temp;
q.push(make_pair(make_pair(x1,0),len));
}
if(vis[0][y1]==0)
{
len ++;
vis[0][y1] = 1;
path[len].c ='D';
path[len].i = 1;
path[len].from = temp;
q.push(make_pair(make_pair(0,y1),len));
}
if(vis[a][y1]==0)///FILL操作
{
len ++;
vis[a][y1] = 1;
path[len].c ='F';
path[len].i = 1;
path[len].from = temp;
q.push(make_pair(make_pair(a,y1),len));
}
if(vis[x1][b]==0)
{
len ++;
vis[x1][b] = 1;
path[len].c ='F';
path[len].i = 2;
path[len].from = temp;
q.push(make_pair(make_pair(x1,b),len));
}
if(x1+y1<=a)///POUR 操作
{
if(vis[x1+y1][0]==0)
{
len ++;
vis[x1+y1][0] = 1;
path[len].c ='P';
path[len].i = 2;
path[len].j = 1;
path[len].from = temp;
q.push(make_pair(make_pair(x1+y1,0),len));
}
}
else
{
if(vis[a][y1-a+x1]==0)
{
len ++;
vis[a][y1-a+x1] = 1;
path[len].c ='P';
path[len].i = 2;
path[len].j = 1;
path[len].from = temp;
q.push(make_pair(make_pair(a,y1-a+x1),len));
}
}
if(x1+y1<=b)
{
if(vis[0][x1+y1]==0)
{
len ++;
vis[0][x1+y1] = 1;
path[len].c ='P';
path[len].i = 1;
path[len].j = 2;
path[len].from = temp;
q.push(make_pair(make_pair(0,x1+y1),len));
}
}
else
{
if(vis[x1+y1-b][b]==0)
{
len ++;
vis[x1+y1-b][b] = 1;
path[len].c ='P';
path[len].i = 1;
path[len].j = 2;
path[len].from = temp;
q.push(make_pair(make_pair(x1+y1-b,b),len));
}
}
}
return -1;
}
void pri(int s)
{
int len2 = 0;
int temp =s;
int num[MAXN];
num[len2++] = temp;
while(path[temp].from!=0)///将所有路径上的点的下标记录下来
{
// printf("----\n");
num[len2++] = path[temp].from;
temp = path[temp].from;
}
printf("%d\n",len2);
for(int i=len2-1;i>=0;i--)
{
if(path[num[i]].c=='F')
{
printf("FILL(%d)\n",path[num[i]].i);
}
else if(path[num[i]].c=='P')
{
printf("POUR(%d,%d)\n",path[num[i]].i,path[num[i]].j);
}
else if(path[num[i]].c=='D')
{
printf("DROP(%d)\n",path[num[i]].i);
}
}
}
void init()
{
len = 0;
path[len].from = 0;///初始化第一个路径点
while(!q.empty()) q.pop();
M(path,0);
M(vis,0);
}
int main()
{
while(~scanf("%d %d %d",&a,&b,&c))
{
init();
int ans = bfs(0,0);///初始情况下没有水
if(ans==-1)
{
printf("impossible\n");
}
else
{
pri(ans);
}
}
return 0;
}