算法笔记_219:泊松分酒(Java)

目录

1 问题描述

2 解决方案

 


1 问题描述

泊松是法国数学家、物理学家和力学家。他一生致力科学事业,成果颇多。有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布。

有一次闲暇时,他提出过一个有趣的问题,后称为:“泊松分酒”。在我国古代也提出过类似问题,遗憾的是没有进行彻底探索,其中流传较多是:“韩信走马分油”问题。

有3个容器,容量分别为12升,8升,5升。其中12升中装满油,另外两个空着。要求你只用3个容器操作,最后使得某个容器中正好有6升油。

下面的列表是可能的操作状态记录:
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
1,8,3
1,6,5

每行3个数据,分别表示12,8,6升容器中的油量

第一行表示初始状态,第二行表示把12升倒入8升容器后的状态,第三行是8升倒入5升,...

当然,同一个题目可能有多种不同的正确操作步骤。

本题目的要求是,请你编写程序,由用户输入:各个容器的容量,开始的状态,和要求的目标油量,程序则通过计算输出一种实现的步骤(不需要找到所有可能的方法)。如果没有可能实现,则输出:“不可能”。

例如,用户输入:
12,8,5,12,0,0,6

用户输入的前三个数是容器容量(由大到小),接下来三个数是三个容器开始时的油量配置,最后一个数是要求得到的油量(放在哪个容器里得到都可以)

则程序可以输出(答案不唯一,只验证操作可行性):
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
1,8,3
1,6,5

每一行表示一个操作过程中的油量状态。

注意:

请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!


2 解决方案

  1 import java.util.ArrayList;
  2 import java.util.Scanner;
  3
  4 public class Main {
  5     public static ArrayList<String> set = new ArrayList<String>();
  6     public static int[] maxN = new int[3];
  7     public static int[] N = new int[3];
  8     public static int ans;
  9     public static int count = 0;
 10
 11     //某start瓶向end瓶中倒
 12     public void getOnetoAnother(int start, int end) {
 13         if(N[start] == 0)
 14             return;
 15         if(maxN[end] > N[end]) {
 16             int low = maxN[end] - N[end];
 17             int temp1 = N[start], temp2 = N[end];
 18             if(low >= N[start]) {
 19                 N[end] = N[end] + N[start];
 20                 N[start] = 0;
 21             } else {
 22                 N[end] = maxN[end];
 23                 N[start] = N[start] - low;
 24             }
 25             StringBuffer s = new StringBuffer("");
 26             s.append(N[0]);
 27             s.append(",");
 28             s.append(N[1]);
 29             s.append(",");
 30             s.append(N[2]);
 31             if(!set.contains(s.toString())) {
 32                 set.add(s.toString());
 33                 count++;
 34             } else {
 35                 N[start] = temp1;
 36                 N[end] = temp2;
 37             }
 38         }
 39     }
 40
 41     public boolean check() {
 42         if(N[0] == ans || N[1] == ans || N[2] == ans) {
 43             for(String s : set)
 44                 System.out.println(s);
 45             return true;
 46         }
 47         return false;
 48     }
 49
 50     public void getResult() {
 51         int max = Math.max(maxN[0], Math.max(maxN[1], maxN[2]));
 52         if(ans > max) {
 53             System.out.println("不可能");
 54             return;
 55         }
 56         while(true) {
 57             int temp = count;
 58             //A瓶向B瓶倒
 59             getOnetoAnother(0, 1);
 60             if(check())
 61                 break;
 62             //B瓶向C瓶倒
 63             getOnetoAnother(1, 2);
 64             if(check())
 65                 break;
 66             //C瓶向A瓶倒
 67             getOnetoAnother(2, 0);
 68             if(check())
 69                 break;
 70             //A瓶向C瓶倒
 71             getOnetoAnother(0, 2);
 72             if(check())
 73                 break;
 74             //C瓶向B瓶倒
 75             getOnetoAnother(2, 1);
 76             if(check())
 77                 break;
 78             //B瓶向A瓶倒
 79             getOnetoAnother(1, 0);
 80             if(check())
 81                 break;
 82             temp = count - temp;
 83             if(temp == 0) {
 84                 System.out.println("不可能");
 85                 return;
 86             }
 87         }
 88     }
 89
 90     public static void main(String[] args) {
 91         Main test = new Main();
 92         Scanner in = new Scanner(System.in);
 93         String S = in.next();
 94         String[] arrayS = S.split(",");
 95         for(int i = 0;i < 3;i++)
 96             maxN[i] = Integer.valueOf(arrayS[i]);
 97         for(int i = 3;i < 6;i++)
 98             N[i - 3] = Integer.valueOf(arrayS[i]);
 99         ans = Integer.valueOf(arrayS[6]);
100         StringBuffer s = new StringBuffer("");
101         s.append(N[0]);
102         s.append(",");
103         s.append(N[1]);
104         s.append(",");
105         s.append(N[2]);
106         set.add(s.toString());
107         test.getResult();
108     }
109 }

运行结果:

测试用例1:
12,8,5,12,0,0,6
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
7,0,5
7,5,0
2,5,5
2,8,2
10,0,2
10,2,0
5,2,5
5,7,0
0,7,5
0,8,4
8,0,4
8,4,0
3,4,5
3,8,1
11,0,1
11,1,0
6,1,5

测试用例2:
30,13,7,30,0,0,5
30,0,0
17,13,0
17,6,7
24,6,0
24,0,6
23,0,7
23,7,0
16,7,7
16,13,1
29,0,1
29,1,0
22,1,7
22,8,0
15,8,7
15,13,2
28,0,2
28,2,0
21,2,7
21,9,0
14,9,7
14,13,3
27,0,3
27,3,0
20,3,7
20,10,0
13,10,7
13,13,4
26,0,4
26,4,0
19,4,7
19,11,0
12,11,7
12,13,5

测试用例3:
31,19,11,31,0,0,5
31,0,0
12,19,0
12,8,11
23,8,0
23,0,8
20,0,11
20,11,0
9,11,11
9,19,3
28,0,3
28,3,0
17,3,11
17,14,0
6,14,11
6,19,6
25,0,6
25,6,0
14,6,11
14,17,0
3,17,11
3,19,9
22,0,9
22,9,0
11,9,11
11,19,1
30,0,1
30,1,0
19,1,11
19,12,0
8,12,11
8,19,4
27,0,4
27,4,0
16,4,11
16,15,0
5,15,11

测试用例4:
65,33,12,65,0,0,18
65,0,0
32,33,0
32,21,12
44,21,0
44,9,12
56,9,0
56,0,9
53,0,12
53,12,0
41,12,12
41,24,0
29,24,12
29,33,3
62,0,3
62,3,0
50,3,12
50,15,0
38,15,12
38,27,0
26,27,12
26,33,6
59,0,6
59,6,0
47,6,12
47,18,0
时间: 2024-12-30 02:30:26

算法笔记_219:泊松分酒(Java)的相关文章

泊松分酒

泊松是法国数学家.物理学家和力学家.他一生致力科学事业,成果颇多. 有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布. 有一次闲暇时,他提出过一个有趣的问题,后称为:"泊松分酒". 在我国古代也提出过类似问题,遗憾的是没有进行彻底探索,其中流传较多是:"韩信走马分油"问题. 有3个容器,容量分别为12升,8升,5升.其中12升中装满油,另外两个空着. 要求你只用3个容器操作,最后使得某个容器中正好有6升油. 下面的列表是可能的操作状态记录: 12,0,

算法笔记_023:拓扑排序(Java)

目录 1 问题描述 2 解决方案 2.1 基于减治法实现 2.2 基于深度优先查找实现 1 问题描述 给定一个有向图,求取此图的拓扑排序序列. 那么,何为拓扑排序? 定义:将有向图中的顶点以线性方式进行排序.即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面. 2 解决方案 2.1 基于减治法实现 实现原理:不断地做这样一件事,在余下的有向图中求取一个源(source)(PS:定义入度为0的顶点为有向图的源),它是一个没有输入边的顶点,然后把它和所有从它出发

算法笔记_132:最大流量问题(Java)

目录 1 问题描述 2 解决方案   1 问题描述 何为最大流量问题? 给定一个有向图,并为每一个顶点设定编号为0~n,现在求取从顶点0(PS:也可以称为源点)到顶点n(PS:也可以称为汇点)后,顶点n能够接收的最大流量.图中每条边的权值为该边的容量,从顶点0到顶点n的某一条路径中最大流量不能超过该路径中任何一条边剩下的容量. 2 解决方案 上述对于最大流量问题的描述是楼主自己个人描述,描述的有点粗暴简略>~<. 求取最大流量问题的的核心要理解三个概念: (1)残留网络 (2)增广路径 (3)

算法笔记_124:密码脱落(Java)

一 问题描述 X星球的考古学家发现了一批古代留下来的密码.这些密码是由A.B.C.D 四种植物的种子串成的序列.仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串).由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征. 你的任务是:给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子. 输入一行,表示现在看到的密码串(长度不大于1000)要求输出一个正整数,表示至少脱落了多少个种子. 例如,输入:ABCBA则程序应该输出:0 再例

算法笔记_027:俄式乘法(Java)

1 问题描述 首先,了解一下何为俄式乘法?此处,借用<算法设计与分析基础>第三版上一段文字介绍: 2 解决方案 具体编码如下: package com.liuzhen.chapter4; public class RussianPeasant { //方法1:递归求解 public void recursionRussian(int m,int n,int result){ if(m < 1) return; if(m == 1) System.out.println("使用递

算法笔记_016:凸包问题(Java)

目录 1 问题描述 2 解决方案 2.1 蛮力法 1 问题描述 给定一个平面上n个点的集合,它的凸包就是包含所有这些点的最小凸多边形,求取满足此条件的所有点. 另外,形象生动的描述: (1)我们可以把这个问题看作如何用长度最短的栅栏把n头熟睡的老虎围起来. (2)也可以这样看:请把所讨论的点想象成钉在胶合板上的钉子,胶合板代表平面.撑开一根橡皮筋圈,把所有的钉子都围住,然后啪一声松开手.凸包就是以橡皮圈为边界的区域.具体示意如下图1所示: 图1  用橡皮筋来解释凸包 2 解决方案 2.1 蛮力法

算法笔记_042:求最小公倍数(Java)

目录 1 问题描述 2 解决方案   1 问题描述 何为最小公倍数?能同时被数字m和数字n整除的最小整数.例如,24和60的最小公倍数等于120.下面请编写相关函数实现求取数字m和n的最小公倍数. 2 解决方案 关于本文求解最小公倍数的思想,来自于<算法设计与分析基础>第三版上一段讲解,具体如下: 具体代码如下: package com.liuzhen.chapter6; public class LeastCommonMultiple { //使用欧几里得算法求解数m和数n最大公约数 pub

算法笔记_225:数字密码发生器(Java)

目录 1 问题描述 2 解决方案   1 问题描述 在对银行账户等重要权限设置密码的时候,我们常常遇到这样的烦恼:如果为了好记用生日吧,容易被破解,不安全:如果设置不好记的密码,又担心自己也会忘记:如果写在纸上,担心纸张被别人发现或弄丢了... 这个程序的任务就是把一串拼音字母转换为6位数字(密码).我们可以使用任何好记的拼音串(比如名字,王喜明,就写:wangximing)作为输入,程序输出6位数字. 变换的过程如下: 第一步. 把字符串6个一组折叠起来,比如wangximing则变为: wa

算法笔记_220:猜算式(Java)

目录 1 问题描述 2 解决方案   1 问题描述 看下面的算式: □□ x □□ = □□ x □□□ 它表示:两个两位数相乘等于一个两位数乘以一个 三位数. 如果没有限定条件,这样的例子很多. 但目前的限定是:这9个方块,表示1~9的9个数字 ,不包含0.该算式中1至9的每个数字出现且只出现一次! 比如:46 x 79 = 23 x 15854 x 69 = 27 x 13854 x 93 = 27 x 186..... 请编程,输出所有可能的情况! 注意:左边的两个乘数交换算同一方案,不要