Week 2 Pour Water —— BFS

题目描述

倒水问题 “fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空

样例

样例输入

2 7 5
2 7 4

样例输出

fill B
pour B A
success 
fill A
pour A B
fill A
pour A B
success

思路

建立状态结构体,包含当前A、B两个杯子中的水量,该状态为第几次操作,前一状态得到现在状态使用的操作,以及操作对应的序号(操作和序号的对应关系也可以用map来映射orz)
本题主要采用BFS,和迷宫有异曲同工之处,每次操作有六种选择:倒空A、倒空B、将A倒入B、将B倒入A、倒满A、倒满B,vis[][]数组用来表示该状态是否出现过,从(0,0)开始入队,BFS,对每个状态都进行六种操作并入队,并将该状态标记为已出现,直到出现目标水量。
输出采用递归判断当前状态是否为初始状态,依次输出。

总结

本题主要思路还是采取BFS,但是对六种选择进行操作时,需要注意A向B倒水以及B向A倒水时,需要判断水量是否能全部转移或者出现容量<水量的情况。

代码

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;

struct node
{
	int x,y;
	int step,pre,op;
};

string operation[6]={"fill A","fill B","empty A","empty B","pour A B","pour B A"};

struct node queue[1000000];
int vis[1000][1000];
int front,rear;
int a,b,c;

void add(int xn,int yn,int stepn,int pre,int op)//入队 
{
	if(vis[xn][yn]==1)
		return;
	vis[xn][yn]=1;
	queue[++rear].x=xn;
	queue[rear].y=yn;
	queue[rear].pre=pre;
	queue[rear].step=stepn+1;
	queue[rear].op=op;	
}

void print(int x)//打印步骤 
{
	if(x==1)
		return;
	print(queue[x].pre);
	cout<<operation[queue[x].op]<<endl;
}

void printAns(int x)//打印最终结果 
{
	print(x);
	cout<<"success"<<endl;
}

void bfs()
{
	queue[++front].x=0;
	queue[front].y=0;
	queue[front].step=0;
	queue[front].pre=1;
	vis[0][0]=1;
	while(front<=rear)
	{
		int x1=queue[front].x;
		int y1=queue[front].y;
		int step1=queue[front].step;
		if(y1==c)
		{
			printAns(front);
			return;
		}
		add(a,y1,step1,front,0);//fill A
		add(x1,b,step1,front,1);//fill B
		add(0,y1,step1,front,2);//empty A
		add(x1,0,step1,front,3);//empty B
		int sub=min(x1,b-y1);
		add(x1-sub,y1+sub,step1,front,4);//pour A B
		sub=min(y1,a-x1);
		add(x1+sub,y1-sub,step1+1,front,5);//pour B A
		front++;
	}	
} 

int main()
{
//	int a,b,c;
	while(cin>>a>>b>>c)
	{
		memset(vis,0,sizeof(vis));
		front=0;
		rear=1;
		bfs();
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yySakura

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值