Pots
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)
题意:
输入数据:A,B,C。A表示容器a容量,B表示容器b容量,C为将要做的事:使任意一个容器装有C容量的水(C<=max(A,B))
你能做三种操作:
1.FILL(i) :将容器i(序号,i=1或2即A和B)用水装满
2.DROP(i):将容器i(序号)里的水倒光
3.POUR(i,j):将容器i里的水倒入j(序号)中。有两种可能性:如果两容器水量之和小于容器j(序号)容量,则容器i里的水被倒光;如果如果两容器水量之和大于容器j(序号)容量,则容器j里装满水。
输出最少操作次数和每次的操作
思路:
哎呀,这题有种似曾相识的感觉。经分析得这题也是有六次操作,和HDU 1495-非常可乐很类似嘛。稍微麻烦点的就是要输出一对操作字符串。既然是字符串的话,结构体里加一个str变量,然后每次strcpy就可以了。思路很类似,详细见注释。
代码示例:
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#define MAX 105
using namespace std;
int A,B,C;
bool vis[MAX][MAX];
struct point {
int vol_a;//容器a
int vol_b;//容器b
int step;//次数统计
char str[MAX][MAX];//字符串拷贝
};
queue<point> que;
bool bfs()
{
//初始化
point p,q;
memset(vis,false,sizeof(vis));
p.vol_a=0,p.vol_b=0,p.step=0;
vis[0][0]=true;
while(!que.empty()) que.pop();
//开始将结点压入队列
que.push(p);
while(!que.empty())
{
p=que.front();
que.pop();
//判断出口并输出
if(p.vol_a==C||p.vol_b==C)
{
cout<<p.step<<endl;
for(int i=1;i<=p.step;i++)
cout<<p.str[i]<<endl;
return true;
}
//把a倒满
if(p.vol_a==0)
{
q=p;
q.vol_a=A;
q.step++;
strcpy(q.str[q.step],"FILL(1)");
if(!vis[q.vol_a][q.vol_b]){
vis[q.vol_a][q.vol_b]=true;
que.push(q);
}
}
//把a中水倒出
else if(p.vol_a<=A)
{
q=p;
q.vol_a=0;
q.step++;
strcpy(q.str[q.step],"DROP(1)");
if(!vis[q.vol_a][q.vol_b])
{
vis[q.vol_a][q.vol_b]=true;
que.push(q);
}
//a->b
if(q.vol_b<B) //如果b没装满 ,才能往b内装
{
q=p;
if(q.vol_a+q.vol_b<=B) //如果 总量都不足以装满b容量
{
q.vol_b=q.vol_a+q.vol_b;
q.vol_a=0;
}
else //如果 总量超过了b容量
{
q.vol_a=q.vol_a+q.vol_b-B; //两句顺序不能反!!
q.vol_b=B;
}
q.step++; //步数统计
strcpy(q.str[q.step],"POUR(1,2)"); //字符串赋给q.str[步数(即可认为是“层次”,bfs每一层都会遍历所有)]
if(!vis[q.vol_a][q.vol_b])
{
vis[q.vol_a][q.vol_b]=true;
que.push(q);
}
}
}
//把b倒满 (不分别解释,与上相对应)
if(p.vol_b==0)
{
q=p;
q.vol_b=B;
q.step++;
strcpy(q.str[q.step],"FILL(2)");
if(!vis[q.vol_a][q.vol_b])
{
vis[q.vol_a][q.vol_b]=true;
que.push(q);
}
}
//把b中水倒出
else if(p.vol_b<=B)
{
q=p;
q.vol_b=0;
q.step++;
strcpy(q.str[q.step],"DROP(2)");
if(!vis[q.vol_a][q.vol_b])
{
vis[q.vol_a][q.vol_b]=true;
que.push(q);
}
//b->a
if(q.vol_a<A)
{
q=p;
if(q.vol_a+q.vol_b<=A)
{
q.vol_a=q.vol_a+q.vol_b;
q.vol_b=0;
}
else
{
q.vol_b=q.vol_a+q.vol_b-A;
q.vol_a=A;
}
q.step++;
strcpy(q.str[q.step],"POUR(2,1)");
if(!vis[q.vol_a][q.vol_b])
{
vis[q.vol_a][q.vol_b]=true;
que.push(q);
}
}
}
}
return false;
}
int main()
{
while(cin>>A>>B>>C&&A&&B&&C)
{
bool flag=bfs();
if(flag==false) cout<<"impossible"<<endl;
}
return 0;
}