Pots

给你两个容量分别为 A 升和 B 升的罐子。可以进行以下操作:

  1. FILL(i)        从水龙头向罐子 i(1 ≤ ≤ 2)灌满水;
  2. DROP(i)      把罐子 i 的水倒空;
  3. POUR(i,j)    从罐子 i 向罐子 j 倒水;此操作后,要么罐子 j 满了(罐子 i 可能还有水),要么罐子 i 空了(所有水都倒到罐子 j 里)。

编写一个程序,找出能使其中一个罐子中恰好有 C 升水的最短操作序列。

输入

第一行包含三个整数 AB 和 C。这些数都在 1 到 100 的范围内,且 C ≤ max(A,B)。

输出

输出的第一行必须包含操作序列的长度 K。接下来的 K 行分别描述一个操作。如果有多个最短长度的操作序列,输出其中任意一个。如果无法达到期望结果,输出文件的第一行必须包含单词 ‘impossible’。

示例

InputOutput
3 5 4
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)

解题思路

本题有3总操作,但操作的对象不同,一共有6种不同操作,题目求最短显然用bfs搜索更好一点

我们在找到终点还要回溯其走过的点,这里可以在结构体里面增加一个变量记录是由哪个点来的

最后记得逆序输出答案

#include<stdio.h>
#include<string.h>
struct bbffss {
	int x;//横坐标
	int y;//纵坐标
	int f;//从哪个点来的
	int s;
	char str[15];
}q[10000005];
int a, b, c, k = 0, top = 0, sum = 0, flag = 0;
int book[101][101], m, n;
char str1[] = "FILL(0)";
char str2[] = "DROP(0)";
char str3[] = "POUR(0,0)";
char sy[100000][15];
void sss(int x, int y,int tail)
{
	switch (x)
	{
	case 1:
		strcpy(q[tail].str, str1);
		q[tail].str[5] += y;
		break;
	case 2:
		strcpy(q[tail].str, str2);
		q[tail].str[5] += y;
		break;
	case 3:
		strcpy(q[tail].str, str3);
		if (y == 1)
		{
			q[tail].str[5] += 1;
			q[tail].str[7] += 2;
		}
		else
		{
			q[tail].str[5] += 2;
			q[tail].str[7] += 1;
		}
		break;
	}
}
void bfs()
{
	int hard = 1, tail = 2, tx, ty;
	book[0][0] = 1;
	q[1].x = 0; q[1].y = 0;
	q[1].f = 0; q[1].s = 0;
	while (hard < tail)
	{
		for (int j = 1; j <= 2; j++)//两种不同的操作对象
		{
			for (int i = 1; i <= 3; i++)//三种操作方式
			{
				//根据操作方式和对象的不同
				switch (i)
				{
				case 1:
					if (j == 1)
					{
						tx = a;
						ty = q[hard].y;
					}
					else
					{
						tx = q[hard].x;
						ty = b;
					}
					break;
				case 2:
					if (j == 1)
					{
						tx = 0;
						ty = q[hard].y;
					}
					else
					{
						tx = q[hard].x;
						ty = 0;
					}
					break;
				case 3:
					m = q[hard].x;
					n = q[hard].y;
					if (j == 1)
					{
						if (b - n >= m)
						{
							tx = 0;
							ty = n + m;
						}
						else
						{
							tx = m - (b - n);
							ty = b;
						}
					}
					else
					{
						if (a - m >= n)
						{
							tx = n + m;
							ty = 0;
						}
						else
						{
							tx = a;
							ty = n - (a - m);
						}
					}
					break;
				}
				if (book[tx][ty] == 1)
					continue;
				book[tx][ty] = 1;//标记存在这种情况
				//入队操作
				q[tail].x = tx; q[tail].y = ty;
				q[tail].f = hard; q[tail].s = q[hard].s + 1;
				sss(i, j, tail);
				if (tx == c || ty == c)//判断是否到达指定容量
				{
					int ff = tail;
					sum = q[tail].s;
					while (ff != 0)
					{
						strcpy(sy[++top], q[ff].str);
						ff = q[ff].f;
						
					}
					flag = 1;
					return;
				}
				tail++;
			}
		}
		hard++;
	}
}
int main()
{
	scanf("%d %d %d", &a, &b, &c);//输入a,b,c
	
	bfs();//进行搜索
	if (flag == 1)//有答案进行输出
	{
		printf("%d\n", sum);
		for (int i = top - 1; i >= 1; i--)//逆序输出
			printf("%s\n", sy[i]);
	}
	else//没有答案
		printf("impossible\n");
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

3分人生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值