题目描述
有一个很大的水缸和二个容量分别为X和Y的水壶,按照以下的规则倒水,问最少经几次倒水后,可得到Z升水
规则1:水缸向水壶1倒水,将水壶1装满;
规则2:水缸向水壶2倒水,将水壶2装满;
规则3:水壶1向水缸倒水,直到水壶1空;
规则4:水壶2向水缸倒水,直到水壶2空;
规则5:水壶1向水壶2倒水,直到水壶1空了或者水壶2满了;
规则6:水壶2向水壶1倒水,直到水壶2空了或者水壶1满了;
输入
只有一行数据,包括以空格分隔的三个数字,分别表示水壶1( <= 100)、 水壶2的水量( <= 100 )以及期望得到的水量( <=100 )。
输出
若经若干次倒水能得到所要求的水量,则输出最少的倒水次数;若无论如何倒水都无法得到规定的水量,则输出No Solution!
样例输入
4 3 1
样例输出
2
AC代码
#include <iostream>
#include <string.h>
using namespace std;
struct point //结构体
{
int x, y, step;
};
bool used[101][101];
point q[20000], s;
int xx, yy, t;
int f = 1, e = 1;
point gen(point u, int cc)//尝试枚举每一个规则
{
point v = u;
v.step = u.step + 1;
//开始枚举规则
if (cc == 1) v.x = xx;//水缸向水壶1倒水,将水壶1装满
else if (cc == 2) v.y = yy;//水缸向水壶2倒水,将水壶2装满
else if (cc == 3) v.x = 0;//水壶1向水缸倒水,直到水壶1空
else if (cc == 4) v.y = 0;//水壶2向水缸倒水,直到水壶2空
else if (cc == 5)//水壶1向水壶2倒水,直到水壶1空了或者水壶2满了
{
if (u.x + u.y <= yy) v.x = 0, v.y = u.x + u.y;//如果y能把x和y的水量都装下
else v.y = yy, v.x = u.x + u.y - yy;//y装不下从x倒过来的水
}
else//水壶2向水壶1倒水,直到水壶2空了或者水壶1满了
{
if (u.x + u.y <= xx) v.y = 0, v.x = u.x + u.y;//如果x能把x和y的水量都装下
else v.x = xx, v.y = u.x + u.y - xx;//x装不下从y倒过来的水
}
return v;
}
int main()
{
scanf ("%d %d %d", &xx, &yy, &t);//xx是x桶的水量,yy是y桶的水量
if (t == 0)
{
printf ("0
");
return 0;
}
memset (used, 0, sizeof (used));//memset
s.x = 0, s.y = 0, s.step = 0;
q[1] = s;
///////////开始宽搜///////////////
while (f <= e)//f是出队下标 e是入队下标
{
point u = q[f++];//选定的元素
for (int i = 1; i <= 6; i++)//尝试枚举6个规则
{
point v = gen(u, i);//v就是将要入队的元素
if (used[v.x][v.y] == 0)
{
if (v.x == t || v.y == t)//任意一个杯子里面有目标水量
{
printf ("%d
", v.step);//就打印步数
return 0;//默默退出
}
q[++e] = v;//入队
used[v.x][v.y] = 1;//表示已经被选择过
}
}
}
printf ("No Solution!
");//如果无法完成
return 0;
}
思路分析
step1
:将初始状态入队
step2
:以初始状态为中心按6个规则向6个方向寻找可能的值入队
step3
:在通过可能的值向6个方向继续拓展,直到找到目标(水壶1 或 水壶2 中的水 等于目标水量)