题目描述
倒水问题 “fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空。
Input
输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质。
Output
你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。
Sample Input
2 7 5
2 7 4
Sample Output
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
解题思路
用结构体记录各个状态,分别为a中的水,b中的水,还有上一个状态,上一个状态进行的操作。
用bfs遍历,每个状态有六条“路”,分别为a倒空,b倒空,a倒满,b倒满,a倒入b,b倒入a。每次判断一下两个杯子中的水量是否为c,是则输出,不是则继续。(数据量较大,用数组没有扩容函数则会runtime error)
完整代码
//用bfs遍历各种情况,分别为a倒空,b倒空,a倒满,b倒满,a倒入b,b倒入a
//用新的结构体记录各个状态,分别为a中的水,b中的水,还有上一个状态。
//每次判断一下两个杯子中的水量是否为c
//preaction:1表示empty A;2表示empty B;3表示fill A;4表示fill B;5表示pour A B;6表示pour B A;
#include<iostream>
using namespace std;
struct State{
int a;
int b;
int pre;
int preaction;
};
void changeLength1D(State*& a, int oldLength, int newLength)
{
State* temp = new State[newLength]; // new array
int number = min(oldLength, newLength); // number to copy
copy(a, a + number, temp);
delete [] a; // deallocate old memory
a = temp;
}
int bfs(int A,int B,int C)
{
State *state=new State[100];//队列
int size=100;
int out[200];
int front=0;
state[0].a=0;
state[0].b=0;
int end=1;
while(front!=end)//即队列不空
{if(end>size-10)
{ changeLength1D(state,size,2*size);
size=2*size;}
//判断6种状态是否有相等的
//1.a中倒空
if(state[front].a>0)
{//cout<<"1"<<endl;
//cout<<"a: "<<state[front].a<<" b: "<<state[front].b<<endl;
state[end].a=0;
state[end].b=state[front].b;
state[end].pre=front;
state[end].preaction=1;
end++;}
//2.b中倒空
if(state[front].b>0)
{//cout<<"2"<<endl;
//cout<<"a: "<<state[front].a<<" b: "<<state[front].b<<endl;
state[end].b=0;
state[end].a=state[front].a;
state[end].pre=front;
state[end].preaction=2;
end++;}
//3.a中倒满
if(state[front].a<A)
{//cout<<"3"<<endl;
//cout<<"a: "<<state[front].a<<" b: "<<state[front].b<<endl;
state[end].a=A;
state[end].b=state[front].b;
state[end].pre=front;
state[end].preaction=3;
if(state[end].a==C)
break;
end++;}
//4.b中倒满
if(state[front].b<B)
{ //cout<<"4"<<endl;
// cout<<"a: "<<state[front].a<<" b: "<<state[front].b<<endl;
state[end].b=B;
state[end].a=state[front].a;
state[end].pre=front;
state[end].preaction=4;
if(state[end].b==C)
break;
end++;}
//5.a倒入b(判断a中是否剩余,b是否倒满,再判断当前状态是否能出现C)
if(state[front].a>0&&state[front].b!=B)
{//cout<<"5"<<endl;
//cout<<"a: "<<state[front].a<<" b: "<<state[front].b<<endl;
if(state[front].a>B-state[front].b)//a中有剩余且b满了
{state[end].a=state[front].a-B+state[front].b;
state[end].b=B;
state[end].pre=front;
state[end].preaction=5;
if(state[end].a==C)//success,输出
break;
end++;}
else//a中没有剩余,b中满不满不确定
{state[end].b=state[front].a+state[front].b;
state[end].a=0;
state[end].pre=front;
state[end].preaction=5;
if(state[end].b==C)//success,输出
break;
end++;
}
}
//6.b倒入a(判断b中是否剩余,a是否倒满,再判断当前状态是否能出现C)
if(state[front].b>0&&state[front].a!=A)
{//cout<<"6"<<endl;
// cout<<"a: "<<state[front].a<<" b: "<<state[front].b<<endl;
if(state[front].b>A-state[front].a)//b中有剩余且a满了
{state[end].b=state[front].b-A+state[front].a;
state[end].a=A;
state[end].pre=front;
state[end].preaction=6;
if(state[end].b==C)//success,输出
break;
end++;}
else//b中没有剩余,a中满不满不确定
{state[end].a=state[front].a+state[front].b;
state[end].b=0;
state[end].pre=front;
state[end].preaction=6;
if(state[end].a==C)//success,输出
break;
end++;
}
}
front++;
}
int i=0;
int pre=state[end].pre;
int preaction=state[end].preaction;
while(pre!=0)
{out[i]=preaction;
preaction=state[pre].preaction;
pre=state[pre].pre;
i++;
}
out[i]=preaction;
for(int m=i;m>=0;m--)
{switch (out[m]){
case 1:
cout<<"empty A"<<endl;
break;
case 2:
cout<<"empty B"<<endl;
break;
case 3:
cout<<"fill A"<<endl;
break;
case 4:
cout<<"fill B"<<endl;
break;
case 5:
cout<<"pour A B"<<endl;
break;
case 6:
cout<<"pour B A"<<endl;
break;
}
}cout<<"success"<<endl;
}
int main(){
int a,b,c;
while(cin>>a>>b>>c)
bfs(a,b,c);
}