一、原题
五、母亲的牛奶(cow.cpp)
【题目描述】
农民约翰有三个容量分别是A,B,C升的桶,A、B、C分别是三个从1到20的整数。
最初,A和B桶都是空的,而C桶是装满牛奶的。
有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。由于节约,牛奶不会有丢失。
写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。
【输入】
第1行:3个整数A,B和C。
【输出】
第1行:升序地列出当A桶是空的时候,C桶牛奶所剩量的所有可能性。
【样例输入】
2 5 10
【样例输出】
5 6 7 8 9 10
二、分析
这道题要用广度优先搜索bfs来做,把3个桶的状态作为一个结点入队,产生式规则是每个结点都可以给其他桶倒牛奶,只要倒入桶的状态还没有入队(需要一个标志数组vis记录3个桶的容量,是否出现过,如果出现过,就不再次入队),就可以入队,当队为空时,bfs结束。查找vist数组所有A桶为空时,C桶的容量,并从小到大依次输出。
三、源程序
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
struct node{
int x,y;
}n;
queue<node>que;
int vis[25][25],M[3],tmp;
void bfs(){//定义广搜函数
while(!que.empty()){//一直循环,直到队列为空
for(int i=0;i<=2;i++)
for(int j=0;j<=2;j++){
int A[3];
A[0]=que.front().x;
A[1]=que.front().y;//读入队列首项
A[2]=M[2]-A[0]-A[1];
if(i==j) continue;
tmp=A[i]+A[j];//定义一个暂时变量用于后面查看
A[j]=min(tmp,M[j]);//取小的
A[i]=tmp-A[j];
if(!vis[A[0]][A[1]]){
vis[A[0]][A[1]]=1;//已经访问过,避免再次访问
n.x=A[0];
n.y=A[1];//把值赋值为临时n,到后面来入队
que.push(n); //入队
}
}
que.pop();//出栈
}
}
int main()
{
//freopen("cow.in","r",stdin);
//freopen("cow.out","w",stdout);//文件的输入输出
scanf("%d%d%d",&M[0],&M[1],&M[2]);//读入
vis[0][0]=1;
n.x=0;
n.y=0;//初始化
que.push(n);//入队
bfs();
int c=0;
for(int i=M[2];i>=0;i--)//输出
if(vis[0][i]==1){
if(c==1) printf(" ");
c=1;
printf("%d",M[2]-i);
}
}