Week2 B - Pour Water
倒水问题 “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
Notes
如果你的输出与Sample Output不同,那没关系。对于某个"A B C"本题的答案是多解的,不能通过标准的文本对比来判定你程序的正确与否。 所以本题由 SPJ(Special Judge)程序来判定你写的代码是否正确。
解题关键 BFS
输出并非倒水过程中水杯中水量
而是输出到水过程中的每一个步骤
记录每次步骤使用 map<> string 记录
判断两杯水水量状态也使用 map<> bool 记录
void bfs(int a,int b){//0,0
st now(a,b,-1);//初始状态
st next;//倒水后的状态
qu.push(now);//入队
stat[now]=1;//map记录此状态
while(!qu.empty()){
now=qu.front();
qu.pop();
if(now.bb==c||now.aa==c){//判断是否有满足c的水量
output(now);//输出
cout<<"success"<<endl;
return;
}
//fill a(0)
if(now.aa!=a1){
next.aa=a1;next.bb=now.bb;next.step=0;
if(stat[next]==0){//此状态未出现过
stat[next]=1;
qu.push(st(next.aa,next.bb,0));//入队
ststep[next]="fill A";
front[next]=now;
}
}
//empty a(1)
if(now.aa!=0){
next.aa=0;next.bb=now.bb;next.step=1;
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,1));
ststep[next]="empty A";
front[next]=now;
}
}
//fill b(2)
if(now.bb!=b1){
next.aa=now.aa;next.bb=b1;next.step=2;
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,2));
ststep[next]="fill B";
front[next]=now;
}
}
//empty b(3)
if(now.bb!=0){
next.aa=now.aa;next.bb=0;next.step=3;
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,3));
ststep[next]="empty B";
front[next]=now;
}
}
//a->b(4)
if(now.aa>=(b1-now.bb)){
next.aa=now.aa-(b1-now.bb);next.bb=b1;next.step=4;
}else{
next.aa=0;next.bb=now.bb+now.aa;next.step=4;
}
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,4));
ststep[next]="pour A B";
front[next]=now;
}
//b->a(5)
if(now.bb>=(a1-now.aa)){
next.bb=now.bb-(a1-now.aa);next.aa=a1;next.step=5;
}else{
next.bb=0;next.aa=now.aa+now.bb;next.step=5;
}
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,5));
ststep[next]="pour B A";
front[next]=now;
}
}
return;
}
全代码
#include<iostream>
#include<queue>
#include<string>
#include<map>
using namespace std;
int a1,b1,c;
struct st{
int aa,bb;
int step;
st(){
aa=-1;bb=-1;step=-1;
}
st(int _aa,int _bb){
aa=_aa;bb=_bb;step=-1;
}
st(int _aa,int _bb,int _step){
aa=_aa;bb=_bb;step=_step;
}
bool operator<(const st &f) const {//重载map <
return aa == f.aa ? bb < f.bb : aa < f.aa;
}
};
map<st,bool> stat;
map<st,string> ststep;
map<st,st>front;
queue<st>qu;
void output(st s){//递归输出
if(ststep.find(s) != ststep.end()){
output(front[s]);
cout<<ststep[s]<<endl;
}
}
void bfs(int a,int b){//0,0
st now(a,b,-1);
st next;
qu.push(now);
stat[now]=1;
while(!qu.empty()){
now=qu.front();
qu.pop();
if(now.bb==c||now.aa==c){
output(now);
cout<<"success"<<endl;
return;
}
//fill a(0)
if(now.aa!=a1){
next.aa=a1;next.bb=now.bb;next.step=0;
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,0));
ststep[next]="fill A";
front[next]=now;
}
}
//empty a(1)
if(now.aa!=0){
next.aa=0;next.bb=now.bb;next.step=1;
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,1));
ststep[next]="empty A";
front[next]=now;
}
}
//fill b(2)
if(now.bb!=b1){
next.aa=now.aa;next.bb=b1;next.step=2;
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,2));
ststep[next]="fill B";
front[next]=now;
}
}
//empty b(3)
if(now.bb!=0){
next.aa=now.aa;next.bb=0;next.step=3;
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,3));
ststep[next]="empty B";
front[next]=now;
}
}
//a->b(4)
if(now.aa>=(b1-now.bb)){
next.aa=now.aa-(b1-now.bb);next.bb=b1;next.step=4;
}else{
next.aa=0;next.bb=now.bb+now.aa;next.step=4;
}
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,4));
ststep[next]="pour A B";
front[next]=now;
}
//b->a(5)
if(now.bb>=(a1-now.aa)){
next.bb=now.bb-(a1-now.aa);next.aa=a1;next.step=5;
}else{
next.bb=0;next.aa=now.aa+now.bb;next.step=5;
}
if(stat[next]==0){
stat[next]=1;
qu.push(st(next.aa,next.bb,5));
ststep[next]="pour B A";
front[next]=now;
}
}
return;
}
int main(){
while(cin>>a1>>b1>>c){
ststep.clear();//每次操作都要清空map
front.clear();
stat.clear();
while (!qu.empty())qu.pop();//每次操作都要清空队列
bfs(0,0);//由两杯水都为空开始
}
}