您的位置:首页 > 其它

【NOIP普及组】【DFS】2016年模拟考试(9.3)——母亲的牛奶

2016-09-12 13:54 876 查看
五、母亲的牛奶(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


----------------------------------------------------------------------------------------------------

这道题……应该,可能,也许,是广搜简单一点。

但是,我用的深搜……花了四五十分钟……

真的不会广搜,找时间补补。

 

大体思路:

就递归,定义vis数组(三维)判重,if(!vis)return; 然后只要此处容量没有满,就将其他两个(也要满足不为空)往这里面倒。总共3个大if,6个小if,还有n个问号表达式(事实上老师不推荐用,容易出问题,换成if也无妨,但有一点点复杂)。

 

代码如下:

#include<cstdio> 5
int a,b,c;
int vis[22][22][22];
void milk(int x,int y,int z)//xyz分别是abc桶剩余的数量
{
if(vis[x][y][z])//判重
return;
vis[x][y][z]=1;//发现一种就记录一种
if(x<a)//判断当前桶是否已满
{
if(y)//其他两个桶只要不为空就能往里倒
milk(a>x+y?x+y:a,a>x+y?0:y-(a-x),z);//这里到下面去解释
if(z)
milk(a>x+z?x+z:a,y,a>x+z?0:z-(a-x));
}
if(y<b)//以此类推
{
if(x)
milk(b>x+y?0:x-(b-y),b>x+y?x+y:b,z);
if(z)
milk(x,b>y+z?y+z:b,b>y+z?0:z-(b-y));
}
if(z<c)
{
if(x)
milk(c>x+z?0:x-(c-z),y,c>x+z?x+z:c);
if(y)
milk(x,c>y+z?0:y-(c-z),c>y+z?y+z:c);
}
}
int main()
{
freopen("cow.in","r",stdin);
freopen("cow.out","w",stdout);//文件输入输出
scanf("%d%d%d",&a,&b,&c);
milk(0,0,c);
for(int i=b;i>=0;i--)
for(int j=0;j<=20;j++)//数据中最大c为20,且需从小到大(升序)输出,所以从0到20查
if(vis[0][i][j])
printf("%d ",j);//没有处理最后的空格
return 0;
}
关于问号表达式应该都知道,然后我拿出一个来解释那个递归:

milk(a>x+y?x+y:a,a>x+y?0:y-(a-x),z);

首先第一个参数:

a>x+y?x+y:a,因为此处是将y(b)桶倒至x(a)桶,所以这里是处理x桶。当将y桶全部倒入x桶都没有达到最大容量(a>x+y)时,就将y全部倒入,返回x+y;反之则是x桶满了,也就是a,所以返回a。

第二个参数:

a>x+y?0:y-(a-x),同上,这里是处理y桶。同上,全部y桶倒入后自然是返回0;反之,也就是y桶没倒完,x桶满了,y桶就只减去x桶还差多少倒满的值(a-x)就行了,返回y-(a-x)。

不关第三个参数的事,所以不变。

                                                                                                                                                                       By WZY
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DFS 深搜