三个水杯 搜索题 bfs

思路:abc三个水杯 一共有六种倒水方式。a-b,a-c ; b-a,b-c;c-d;广搜着6种方式即可。但是得判断杯子里的水放进另外一个杯子放不放的下,另外一个杯子需要多少水,杯子子里有没有水可放。不要忘记目标和初始状态一样那种情况。

三个水杯

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数N(0<N<50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
2
6 3 1
4 1 1
9 3 2
7 1 1
样例输出
3
-1
代码:

 
#include<stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define QUEUELEN 1000000
int d,b,c, flag;//abc表示三个杯子的容积
int vis[101][101][101];

typedef struct  
{
	int x; 
	int y;
	int z;
	int pre;//倒水的次数
}DATA;//xyz表示三个杯子现在有多少水。
DATA data[QUEUELEN];
typedef struct  
{
	
	int head;
	int tail;
}SQType;
//队列的初始化
SQType *SQTypeInit()
{
	SQType *q;
	if(q=(SQType *)malloc(sizeof(SQType)))
	{
		q->head=0;
		q->tail=0;
        return q;
	}
	else
	{
		return NULL;
	}
}
//判断空队列
int SQTypeIsEmpty(SQType *q)
{
	int temp;
	temp=q->head==q->tail;
	return temp;

}//入队 
int InSQType(SQType *q,DATA a)
{
	if (q->tail==QUEUELEN)
	{
		printf("队列满鸟。。。");
		return 0;
	}
	else
	{
		data[q->tail++]=a;
		return 1;
	}
}

//出队列
int  OutSQType(SQType *q,DATA &a)
{
	if(q->head==q->tail)
	{
	   printf("亲,队列是空的。。。");
	   return 0;
	}
	else
{  a=data[q->head++];
   
   return 1;
		
	}

}

bool bfs(int x,int y,int z,int zx,int zy,int zz)
{  if(x==zx&&y==zy&&z==zz)//目标是出事状态。 {
               printf("%d\n",0);flag=1;return 1;}
	SQType *shuibei=SQTypeInit();
	DATA a={x,y,z,0};
	InSQType(shuibei,a);
	
	vis[x][y][z]=1;
	while(!SQTypeIsEmpty(shuibei))
	{   OutSQType(shuibei,a);
		if(a.x!=0&&a.y<b)
	{   int nx=a.x-(b-a.y)>0?a.x-(b-a.y):0;//判断a杯子倒水能不能全部倒进b杯子。能则nx=0;否则等于a水-b杯子需要的水
		int ny=a.x-(b-a.y)>0?a.y+b-a.y:a.y+a.x;判断a杯子的水是否能装满自己 能则等于b不能则等于 a水加b水
		int nz=a.z;
		if(nx==zx&&ny==zy&&nz==zz)
		{
			printf("%d\n",a.pre+1);flag=1;return 1;
		}
		if(vis[nx][ny][nz]==0) 
		{  
			DATA n;
			n.x=nx;
			n.y=ny;
			n.z=nz;
			n.pre=a.pre+1;
			InSQType(shuibei,n);
			vis[nx][ny][nz]=1;
		}
	}
	if(a.x!=0&&a.z<c)
	{   int nx=a.x-(c-a.z)>0?a.x-(c-a.z):0;//同上面的原理一样
		int ny=a.y;
		int nz=a.x-(c-a.z)>0?a.z+(c-a.z):a.z+a.x;
		if(nx==zx&&ny==zy&&nz==zz)
		{
			printf("%d\n",a.pre+1);flag=1;return 1;
		}
		if(vis[nx][ny][nz]==0) 
		{
		
			DATA n;
			n.x=nx;
			n.y=ny;
			n.z=nz;
			n.pre=a.pre+1;
		   InSQType(shuibei,n);
		   vis[nx][ny][nz]=1;
		}
	}
	if(a.y!=0)//b杯子有水
	{
		int nx=a.x+a.y;b杯子倒入a杯子不需要考虑 直接可以倒进去
		int ny=0;
		int nz=a.z;
		if(nx==zx&&ny==zy&&nz==zz)
		{
			printf("%d\n",a.pre+1);flag=1;return 1;
			
		}
		if(vis[nx][ny][nz]==0) 
		{
			DATA n;
			n.x=nx;
			n.y=ny;
			n.z=nz;
			n.pre=a.pre+1;
		   InSQType(shuibei,n);
		   vis[nx][ny][nz]=1;
		}
	}
		if(a.y!=0&&a.z<c)
	{
		int nx=a.x;
		int ny=a.y-(c-a.z)>0?a.y-(c-a.z):0;
		int nz=a.y-(c-a.z)>0?a.z+(c-a.z):a.z+a.y;
		if(nx==zx&&ny==zy&&nz==zz)
		{
			printf("%d\n",a.pre+1);flag=1;return 1;
			
		}
		if(vis[nx][ny][nz]==0 )
		{
			DATA n;
			n.x=nx;
			n.y=ny;
			n.z=nz;
			n.pre=a.pre+1;
		   InSQType(shuibei,n);
		   vis[nx][ny][nz]=1;
		}
	}
	if(a.z!=0)
	{
	   int nx=a.x+a.z;
        int nz=0; 
		int ny=a.y;
		
		if(nx==zx&&ny==zy&&nz==zz)
		{
			printf("%d\n",a.pre+1);flag=1;return 1;
			
		}
		if(vis[nx][ny][nz]==0) 
		{
			DATA n;
			n.x=nx;
			n.y=ny;
			n.z=nz;
			n.pre=a.pre+1;
		   InSQType(shuibei,n);
		   vis[nx][ny][nz]=1;
		}
	}
	if(a.z!=0&&a.y<b)
	{
		int nx=a.x;
		int ny=b-a.y>a.z?a.y+a.z:b;判断b杯子能否装下c杯子里的水能装下则等于a.y+a.z c杯子此时没水。装不下则可以装满就直接等于b c此时等于c杯子的水减去b杯子需要多少水。
		int nz=b-a.y>a.z?0:a.z-(b-a.y);
		if(nx==zx&&ny==zy&&nz==zz)
		{
			printf("%d\n",a.pre+1);flag=1;
			return 1;
			
		}
		if(vis[nx][ny][nz]==0) 
		{
			DATA n;
			n.x=nx;
			n.y=ny;
			n.z=nz;
			n.pre=a.pre+1;
		   InSQType(shuibei,n);
		   vis[nx][ny][nz]=1;
		}
	}
		
	
	}
	
}
int main()
{
	int n,za,zb,zc;
	scanf("%d",&n);
	while(n--)
	{   flag=0;
		scanf("%d%d%d",&d,&b,&c);
		scanf("%d%d%d",&za,&zb,&zc);
		memset(vis,0,sizeof(vis));
		bfs(d,0,0,za,zb,zc);
		if(flag==0)printf("%d\n",-1);
	
	}
}        



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值