分红酒

题目描述

标题:分红酒
  有4个红酒瓶子,它们的容量分别是:9升, 7升, 4升, 2升
  开始的状态是 [9,0,0,0],也就是说:第一个瓶子满着,其它的都空着。
  允许把酒从一个瓶子倒入另一个瓶子,但只能把一个瓶子倒满或把一个瓶子倒空,不能有中间状态。这样的一次倒酒动作称为1次操作。
  假设瓶子的容量和初始状态不变,对于给定的目标状态,至少需要多少次操作才能实现?
  本题就是要求你编程实现最小操作次数的计算。
  输入:最终状态(逗号分隔)
  输出:最小操作次数(如无法实现,则输出-1)

例如:
输入:
9,0,0,0
应该输出:
0
输入:
6,0,0,3
应该输出:
-1
输入:
7,2,0,0
应该输出:
2

对于编程题目,要求选手给出的解答完全符合ANSI C++标准,不能使用诸如绘图、Win32API、中断调用、硬件操作或与操作系统相关的API。
代码中允许使用STL类库,但不能使用MFC或ATL等非ANSI c++标准的类库。例如,不能使用CString类型(属于MFC类库)。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意选择自己使用的编译环境。

分析


#include <stdio.h>
#include <math.h>
#include <string.h>
#define MAX 1500

struct ST                       //定义一个结构体,记录某个状态的各个酒杯的值
{
	int a, b, c, d;
}qu[MAX];

int visit[10][8][5];            //用于保存某个状态是否出现
int step[10][8][5][3];          //用于记录达到某个状态的最短路径
int front = -1, tail = 0;       //
int A = 9, B = 7, C = 4, D = 2; //各个酒杯的最大值
int ea, eb, ec, ed;             //输入的最终状态

int min(int x, int y, int z)    //返回一个杯子能够向另一个杯子倒酒的量
{
	if(x < z - y)
		return x;
	return z - y;
}

int EnterJudge(int x, int y, int z, int w) //判断某个状态是否出现,若出现则入队列
{
	if(visit[x][y][z] == 0)
	{
		++tail;
		qu[tail].a = x;
		qu[tail].b = y;
		qu[tail].c = z;
		qu[tail].d = w;
		visit[x][y][z] = 1;
		return 1;
	}
	return 0;
}

int bfs()                             //广度优先搜索
{
	qu[0].a = 9;                      //初始状态入队列
	qu[0].b = 0;
	qu[0].c = 0;
	qu[0].d = 0;

	int temp, at, bt, ct, dt;
	while(front < tail)              //队列不空时循环
	{
		++front;
		if(qu[front].a == ea && qu[front].b == eb
			&&qu[front].c == ec && qu[front].d == ed)
		{
			return step[ea][eb][ec][ed];    //找到要求的状态,返回最小次数
		}
		

		if(qu[front].a > 0 && qu[front].b < B) //a向b倒水
		{
			temp = min(qu[front].a, qu[front].b, B);
			at = qu[front].a - temp;
			bt = qu[front].b + temp;
			ct = qu[front].c;
			dt = qu[front].d;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
		if(qu[front].a > 0 && qu[front].c < C) //a向c倒水
		{
			temp = min(qu[front].a, qu[front].c, C);
			at = qu[front].a - temp;
			bt = qu[front].b;
			ct = qu[front].c + temp;
			dt = qu[front].d;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
		if(qu[front].a > 0 && qu[front].d < D) //a向d倒水
		{
			temp = min(qu[front].a, qu[front].d, D);
			at = qu[front].a - temp;
			bt = qu[front].b;
			ct = qu[front].c;
			dt = qu[front].d + temp;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}

		if(qu[front].b > 0 && qu[front].a < A) //b向a倒水
		{
			temp = min(qu[front].b, qu[front].a, A);
			at = qu[front].a + temp;
			bt = qu[front].b - temp;
			ct = qu[front].c;
			dt = qu[front].d;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
		if(qu[front].b > 0 && qu[front].c < C) //b向c倒水
		{
			temp = min(qu[front].b, qu[front].c, C);
			at = qu[front].a;
			bt = qu[front].b - temp;
			ct = qu[front].c + temp;
			dt = qu[front].d;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
		if(qu[front].b > 0 && qu[front].d < D) //b向d倒水
		{
			temp = min(qu[front].b, qu[front].d, D);
			at = qu[front].a;
			bt = qu[front].b - temp;
			ct = qu[front].c;
			dt = qu[front].d + temp;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}

		if(qu[front].c > 0 && qu[front].a < A) //c向a倒水
		{
			temp = min(qu[front].c, qu[front].a, A);
			at = qu[front].a + temp;
			bt = qu[front].b;
			ct = qu[front].c - temp;
			dt = qu[front].d;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
		if(qu[front].c > 0 && qu[front].b < B) //c向b倒水
		{
			temp = min(qu[front].c, qu[front].b, B);
			at = qu[front].a;
			bt = qu[front].b + temp;
			ct = qu[front].c - temp;
			dt = qu[front].d;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
		if(qu[front].c > 0 && qu[front].d < D) //c向d倒水
		{
			temp = min(qu[front].c, qu[front].d, D);
			at = qu[front].a;
			bt = qu[front].b;
			ct = qu[front].c - temp;
			dt = qu[front].d + temp;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}

		if(qu[front].d > 0 && qu[front].a < A) //d向a倒水
		{
			temp = min(qu[front].d, qu[front].a, A);
			at = qu[front].a + temp;
			bt = qu[front].b;
			ct = qu[front].c;
			dt = qu[front].d - temp;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
		if(qu[front].d > 0 && qu[front].b < B) //d向b倒水
		{
			temp = min(qu[front].d, qu[front].b, B);
			at = qu[front].a;
			bt = qu[front].b + temp;
			ct = qu[front].c;
			dt = qu[front].d - temp;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
		if(qu[front].d > 0 && qu[front].c < C) //d向c倒水
		{
			temp = min(qu[front].d, qu[front].c, C);
			at = qu[front].a;
			bt = qu[front].b;
			ct = qu[front].c + temp;
			dt = qu[front].d - temp;
			if(EnterJudge(at, bt, ct, dt))
				step[at][bt][ct][dt] = 
				step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 
		}
	}

	return -1;
}

int main()
{
	memset(step, 0, sizeof(step));
	memset(visit, 0, sizeof(visit));
	
	scanf("%d,%d,%d,%d", &ea, &eb, &ec, &ed);

	int cnt = bfs();

	printf("%d\n", cnt);

	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值