一、题目描述
【题目描述】
农民约翰有三个容量分别是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
二、分析
这道题一看就知道是用搜索算法,用深搜算法和广搜算法都可以做,首先要考虑6种倒牛奶的情况
1.a---->b
2.a---->c
3.b---->a
4.b---->c
5.c---->a
6.c---->b
以上的情况都要考虑目标桶是否溢出,总情况数为6*2=12
假设 a桶的容量为2,b桶的容量为5,
a桶目前的牛奶为0,b桶目前的牛奶为3。
如果运行b---->a后,a就等于2,b就等于1。
另一种情况就是不够的情况,
假设 a桶的容量为2,b桶的容量为5,
a桶目前的牛奶为2,b桶目前的牛奶也为2。
如果运行b---->a后,a就等于0,b就等于4。
还有两种特殊的情况,a---->c和b---->c,
因为a桶和b桶无论怎么倒都不会让c桶溢出,
所以总情况数为12-2=10,
程序就不会超时了,
下面是AC广搜伪代码:
#include<cstdio>
#include<queue>
using namespace std;
int s[35];//最终答案
bool vis[25][25][25];//判断重复情况,可以简化为2维
struct node{
int x,y,z;
}t,u;
queue<node> q;
int main()
{
freopen("cow.in","r",stdin);
freopen("cow.out","w",stdout);
int a,b,c,i,j,f;
f=0;
scanf("%d%d%d",&a,&b,&c);
t.x=0;
t.y=0;
t.z=c;
q.push(t);
vis[0][0][c]=1;
while(!q.empty())
{
t=q.front();
q.pop();
if(t.x==0)//储存解
s[t.z]=1;
if(t.x!=0)//A
{
if(t.x+t.y>b){//A -----> B 多的情况
u.x=(t.x+t.y)-b;
u.y=b;
u.z=t.z;//不变
if(vis[u.x][u.y][u.z]==0){//判断重复情况
vis[u.x][u.y][u.z]=1;
q.push(u);
}
}
else{//A -----> B 少的情况
u.x=0;//end
u.y=t.x+t.y;
u.z=t.z;//不变
if(vis[u.x][u.y][u.z]==0){//判断重复情况
vis[u.x][u.y][u.z]=1;
q.push(u);
}
}
//A -----> C 多(不考虑)
//A -----> C shao
}
if(t.y!=0)//B
if(t.z!=0)//C
}
//输出;
}
完整代码请查看我的代码片。