【2016普及组模拟考试】05 搜索 cow(母亲的牛奶)

母亲的牛奶cow.cpp

【题目描述】

农民约翰有三个容量分别是ABC升的桶,ABC分别是三个从120的整数。

最初,AB桶都是空的,而C桶是装满牛奶的。

有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。由于节约,牛奶不会有丢失。

写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。

【输入】

1行:3个整数ABC

【输出】

1行:升序地列出当A桶是空的时候,C桶牛奶所剩量的所有可能性。

【样例输入】

2 5 10

【样例输出】

5 6 7 8 9 10

    这道题有些(其实是很)难把代码写短,一开始bfs用了178(不要惊讶,我没有多打一个8)行,呵呵~于是为了更精简,我把六个鬼祟的if语句改成了for双重循环if一次搞定,还把三维vis变成了二维,改变挺大的,但是……居然只有五分!!!然后我气愤的使用了随机数函数,疯狂和同学对答案(对拍,嗯,对拍),居然全对,可是交上去还是五分……还是把大部分数据都能过的代码公布,希望神犇们指出错误!代码如下:

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
struct node
{
	int x;
	int y;
};
queue<node>que;
int vis[25][25];
int M[3];
void bfs()
{
	while(!que.empty())
	{
		for(int i=0;i<=2;i++)
		{
			for(int j=0;j<=2;j++)
			{
				int A[3]={que.front().x,que.front().y,M[2]-A[0]-A[1]};
				if(i==j)
				{
					continue;
				}
				int s=A[i]+A[j];
				A[j]=min(s,M[j]);
				A[i]=s-A[j];
				if(!vis[A[0]][A[1]])
				{
					vis[A[0]][A[1]]=1;
					node n;
					n.x=A[0];
					n.y=A[1];
					que.push(n);
				}
			}
		}
		que.pop();
	}
}
int main()
{
	//freopen("cow.in","r",stdin);
	//freopen("cow.out","w",stdout);
	//freopen("1.txt","r",stdin);
	scanf("%d%d%d",&M[0],&M[1],&M[2]);
	//for(M[0]=1;M[0]<=20;M[0]++)
	//{
		//for(M[1]=1;M[1]<=20;M[1]++)
		//{
			//for(M[2]=1;M[2]<=20;M[2]++)
			//{
				vis[0][0]=1;
				node n;
				n.x=0;
				n.y=0;
				que.push(n);
				bfs();
				int c=0;
				//printf("%d %d %d:",M[0],M[1],M[2]);
				for(int i=M[2];i>=0;i--)
				{
					if(vis[0][i]==1)
					{
						if(c==1)
						{
							printf(" ");
						}
						c=1;
						printf("%d",M[2]-i);
					}
				}
				memset(vis,0,sizeof(vis));
				//printf("\n");
			//}
		//}
	//}
}</span></strong>

    终于发现了错误了!我在赋A[2]初值的时候,就用到了A[0]和A[1],结果有时候就会莫名其妙的炸了……然后这是我的AC代码:

#include<cstdio>  
#include<queue>  
#include<algorithm>  
#include<cstring>  
using namespace std;  
struct node  
{  
    int x;  
    int y;  
};//定义结构体
queue<node>que;//队列  
int vis[25][25];//标记数组
int M[3];//牛奶上限
void bfs()  
{  
    while(!que.empty())//队列非空运行
    {
        for(int i=0;i<=2;i++)//枚举六个方向
        {
            for(int j=0;j<=2;j++)
            {  
				int A[3]={que.front().x,que.front().y};//现在的牛奶数量
				A[2]=M[2]-A[0]-A[1];
                if(i==j)//相等则跳过
                {  
                    continue;  
                }  
                int s=A[i]+A[j];//s为两桶牛奶之和
                A[j]=min(s,M[j]);//要么倒满,要么倒完,取小的一个
                A[i]=s-A[j];//另外一个为和减去那一个
                if(!vis[A[0]][A[1]])//如果没有标记过,则进入
                {  
                    vis[A[0]][A[1]]=1;//标记
                    node n;
                    n.x=A[0];  
                    n.y=A[1];  
                    que.push(n);//入队 
                }  
            }  
        }  
        que.pop();//出队
    }  
}  
int main()
{
    //freopen("cow.in","r",stdin);//freopen输入
    //freopen("cow.out","w",stdout);//freopen输出
    scanf("%d%d%d",&M[0],&M[1],&M[2]);//读入
	vis[0][0]=1;//标记原始点
	node n;
	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)//当B桶可以为i时,C桶便多了一种状态
		{
			if(c==1)
			{
				printf(" ");
			}
			c=1;
			printf("%d",M[2]-i);//输出
		}
	}
}  


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值