分油问题

分油问题

Description

设有大小不等的3个无刻度的油桶,分别能盛满 X、Y、Z(都小于等于 100)升油,初始时第一个油桶盛满,另外两个为空。现在,要想在某一瓶中分出 T升油。分油时可把一个桶里的油倒入另外的桶中,或者将桶中的油倒空。设计一种以最少步骤的分油方案。

Input

第一行:X Y Z {设第一个油桶 X 已装满油}
第二行:T {要分出的目标油量}

Output

输出最少步数,若无法分出 T 升油,则输出“NO ANSWER! ” 。

Sample Input

80 50 30
60

Sample Output

3

Source

BFS,枚举

Solution

分情况讨论从每一个油壶里倒油的情况,用队列实现搜索

Code

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

int x, y, z, t;
int p[101][101][101];
queue <int> a, b, c, ans;
bool bj;

int main() {
  scanf("%d %d %d %d", &x, &y, &z, &t);
  if (x < t) {printf("NO ANSWER!\n"); return 0;}
  a.push(x), b.push(0), c.push(0), ans.push(0);
  do {
    int a1 = a.front(), b1 = b.front(), c1 = c.front(), d1 = ans.front();
    if (a1 == t || b1 == t || c1 == t) {bj = true; break;}
    if (a1 > 0) {
      if (p[a1 - min(a1, y - b1)][b1 + min(a1, y - b1)][c1] == 0 && y > b1)//1 --> 2
	a.push(a1 - min(a1, y - b1)), b.push(b1 + min(a1, y - b1)), c.push(c1), ans.push(d1 + 1),
	p[a1 - min(a1, y - b1)][b1 + min(a1, y - b1)][c1] = 1;
      if (p[a1 - min(a1, z - c1)][b1][c1 + min(a1, z - c1)] == 0 && z > c1)//1 --> 3
	a.push(a1 - min(a1, z - c1)), b.push(b1), c.push(c1 + min(a1, z - c1)), ans.push(d1 + 1),
	p[a1 - min(a1, z - c1)][b1][c1 + min(a1, z - c1)] = 1;
      if (p[0][b1][c1] == 0)//empty
	a.push(0), b.push(b1), c.push(c1), ans.push(d1 + 1), p[0][b1][c1] = 1;
    }
    if (b1 > 0) {
      if (p[a1 + min(b1, x - a1)][b1 - min(b1, x - a1)][c1] == 0 && x > a1)//2 --> 1
	a.push(a1 + min(b1, x - a1)), b.push(b1 - min(b1, x - a1)), c.push(c1), ans.push(d1 + 1),
	p[a1 + min(b1, x - a1)][b1 - min(b1, x - a1)][c1] = 1;
      if (p[a1][b1 - min(b1, z - c1)][c1 + min(b1, z - c1)] == 0 && z > c1)//2 --> 3
	a.push(a1), b.push(b1 - min(b1, z - c1)), c.push(c1 + min(b1, z - c1)), ans.push(d1 + 1),
	p[a1][b1 - min(b1, z - c1)][c1 + min(b1, z - c1)] = 1;
      if (p[a1][0][c1] == 0)//empty
	a.push(a1), b.push(0), c.push(c1), ans.push(d1 + 1), p[a1][0][c1] = 1;
    }
    if (c1 > 0) {
      if (p[a1 + min(c1, x - a1)][b1][c1 - min(c1, x - a1)] == 0 && x > a1)//3 --> 1
	a.push(a1 + min(c1, x - a1)), b.push(b1), c.push(c1 - min(c1, x - a1)), ans.push(d1 + 1),
	p[a1 + min(c1, x - a1)][b1][c1 - min(c1, x - a1)] = 1;
      if (p[a1][b1 + min(c1, y - b1)][c1 - min(c1, y - b1)] == 0 && y > b1)//3 --> 2
	a.push(a1), b.push(b1 + min(c1, y - b1)), c.push(c1 - min(c1, y - b1)), ans.push(d1 + 1),
	p[a1][b1 + min(c1, y - b1)][c1 - min(c1, y - b1)] = 1;
      if (p[a1][b1][0] == 0)//empty
	a.push(a1), b.push(b1), c.push(0), ans.push(d1 + 1), p[a1][b1][0] = 1;
    }
    a.pop(), b.pop(), c.pop(), ans.pop();
  } while(!a.empty());
  if (bj == true) printf("%d\n", ans.front());
  else printf("NO ANSWER!\n");
  return 0;
}

Summary

一开始被OJ上的输出欺骗了,NO ANSWER!中的“!”是英文的不是中文的,但是题目中说是中文的,WA了一次


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分油问题是一个经典的逻辑谜题,可以使用MATLAB编写程序来解决。 以下是一种解决方案: 1. 首先,定义三个变量A、B、C,分别表示三个瓶子中的油量。例如,A = 8 表示A瓶中有8升油。 2. 然后,定义一个函数check_state(A, B, C),用于检查当前状态是否合法。条件是:每个瓶子的油量必须大于等于0且小于等于其容量,即 0 <= A <= 8,0 <= B <= 5,0 <= C <= 3。 3. 接下来,定义一个函数find_solution(A, B, C),用于找到解决方案。通过递归搜索所有可能的倒油方案,找到一种符合条件的方案即可。 4. 在find_solution(A, B, C)函数中,先检查当前状态是否合法。如果不合法,返回空数组[]。如果合法,尝试所有可能的倒油方案,并递归调用find_solution(A, B, C)函数,直到找到一种符合条件的方案。 5. 当找到解决方案,返回一个包含每一步操作的矩阵M。例如,M = [1 2; 2 3; 3 1] 表示第一步将A瓶中的油倒入B瓶中,第二步将B瓶中的油倒入C瓶中,以此类推。 6. 最后,输出解决方案即可。 注意:这只是一种简单的解决方案,可能存在更加高效的算法。以下是一个示例代码: ```matlab function M = find_solution(A, B, C) if ~check_state(A, B, C) M = []; return; end if A == 4 && B == 4 M = [A B C]; return; end M = []; % 将A倒入B if A > 0 && B < 5 tmp = min(A, 5 - B); M = find_solution(A - tmp, B + tmp, C); if ~isempty(M) M = [[A B C]; M]; return; end end % 将A倒入C if A > 0 && C < 3 tmp = min(A, 3 - C); M = find_solution(A - tmp, B, C + tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将B倒入A if B > 0 && A < 8 tmp = min(B, 8 - A); M = find_solution(A + tmp, B - tmp, C); if ~isempty(M) M = [[A B C]; M]; return; end end % 将B倒入C if B > 0 && C < 3 tmp = min(B, 3 - C); M = find_solution(A, B - tmp, C + tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将C倒入A if C > 0 && A < 8 tmp = min(C, 8 - A); M = find_solution(A + tmp, B, C - tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将C倒入B if C > 0 && B < 5 tmp = min(C, 5 - B); M = find_solution(A, B + tmp, C - tmp); if ~isempty(M) M = [[A B C]; M]; return; end end end function flag = check_state(A, B, C) flag = (0 <= A && A <= 8) && (0 <= B && B <= 5) && (0 <= C && C <= 3); end ``` 使用方法: ```matlab M = find_solution(8, 0, 0); % 从A瓶中开始倒油 disp(M); ``` 输出结果: ``` 8 0 0 3 5 0 3 2 3 6 2 0 6 0 2 1 5 2 1 4 3 4 4 0 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值