非常可乐-特殊的BFS题

                                                                                                                        非常可乐

Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u

Description

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。
 

Input

三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。
 

Output

如果能平分的话请输出最少要倒的次数,否则输出"NO"。
 

Sample Input

    
    
7 4 3 4 1 3 0 0 0
 

Sample Output

  
  
NO 3

BFS涉及的范围非常广,这种题目也依然是暴利广搜一下就出来了,不过要想好一个问题,就是我们平时用BFS写迷宫题目时候那个next在这是怎样得出来的呢?这肯定不是坐标的变换,第二就是当时那个vst,防止你重复去判断一个点,在这道题又要怎么去定义这个vst呢?

我的思路十分简单粗暴,也不管那么多了,vst直接开一个三维数组来代替,大小为105*105*105,一开始初始化为0,如果出现一种新情况,就把vst[i][j][k]=1。然后就是他这个分配,我是分成了六种情况,s分给n,s分给m,n分给s,n分给m,m分给s,m分给n。这就可以得到next了,不像迷宫那些那么方便,这六种情况都要自己手敲出来,没有循环可言。。。

代码如下:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define swap(a,b) {int c=a;a=b;b=c;}
const int maxn=105;
bool vst[maxn][maxn][maxn],flag;
int s,n,m;

struct State
{
	int x,y,z;
	int Step_Counter;
}t;

bool Check_State(State st) 
{
	if(st.x>=0 && st.x <=s && st.y>=0 && st.y <=n && st.z>=0 && st.z <=m && !vst[st.x][st.y][st.z])	
		return 1;
	else 
		return 0;
}

void bfs(State st)
{
	int tmp;
	queue <State> q; 
	State now,next; 
	st.Step_Counter=0; 
	q.push(st);
	vst[st.x][st.y][st.z]=1; 
	while(!q.empty())
	{
		now=q.front(); 
		if(now.x==now.z&&now.y==0) 
		{
			printf("%d\n",now.Step_Counter);
			flag=1;
			return;
		}
		next.Step_Counter=now.Step_Counter+1;
		if(now.x!=0)//从x分配下去 
		{
			//************************
			tmp=now.x-(n-now.y);//x分配给y 
			if(tmp<0)//如果x全部分配给y y却仍未满 
			{
				next.x=0;//只把能分配的分配 
				next.y=now.y+now.x;//直接补上x 
			}
			else
			{
				next.x=tmp;
				next.y=now.y+(n-now.y);
			}	
			next.z=now.z;
			if(Check_State(next))
			{
				q.push(next);
				vst[next.x][next.y][next.z]=1;
			}
			//*************************//x分配给z 
			tmp=now.x-(m-now.z);
			if(tmp<0)
			{
				next.x=0;
				next.z=now.z+now.x;
			}
			else
			{
				next.x=tmp;
				next.z=now.z+(m-now.z);
			}
			next.y=now.y;
			if(Check_State(next))
			{
				q.push(next);
				vst[next.x][next.y][next.z]=1;
			}
		}
		if(now.y!=0)//从y分配下去 
		{
			//*******************************
			tmp=now.y-(s-now.x);//y分配给x 
			if(tmp<0)
			{
				next.y=0;
				next.x=now.x+now.y;
			}
			else
			{
				next.y=tmp;
				next.x=now.x+(s-now.x);
			}			
			next.z=now.z;
			if(Check_State(next))
			{
				q.push(next);
				vst[next.x][next.y][next.z]=1;
			}
			//*******************************
			tmp=now.y-(m-now.z);//y分配给z 
			if(tmp<0)
			{
				next.y=0;
				next.z=now.z+now.y;
			}
			else
			{
				next.y=tmp;
				next.z=now.z+(m-now.z);
			}
			next.x=now.x;
			if(Check_State(next))
			{
				q.push(next);
				vst[next.x][next.y][next.z]=1;
			}
			
		}
		if(now.z!=0)//从z分配下去 
		{
			//************************
			tmp=now.z-(s-now.x);//z分配给x 
			if(tmp<0)
			{
				next.z=0;
				next.x=now.x+now.z;
			}
			else
			{
				next.z=tmp;
				next.x=now.x+(s-now.x);
			}
			next.y=now.y;			
			if(Check_State(next))
			{
				q.push(next);
				vst[next.x][next.y][next.z]=1;
			}
			//**************************
			tmp=now.z-(n-now.y);//z分配给y 
			if(tmp<0)
			{
				next.z=0;
				next.y=now.y+now.z;
			}
			else
			{
				next.z=tmp;
				next.y=now.y+(n-now.y);
			}
			next.x=now.x;
			if(Check_State(next))
			{
				q.push(next);
				vst[next.x][next.y][next.z]=1;
			}
		}
		q.pop(); 
	}
	return;
}

int main()
{
	while(scanf("%d%d%d",&s,&n,&m)!=EOF)
	{
		if(n+m+s==0)
			break;
		if(n>m)
			swap(n,m);
		memset(vst,0,sizeof(vst));
		t.x=s;
		t.y=0;
		t.z=0;
		if(s%2!=0)
		{
			printf("NO\n");
			continue;
		}
		flag=0;
		bfs(t);
		if(flag==0)
			printf("NO\n");
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值