• 泊松分酒


    /* 
     泊松是法国数学家、物理学家和力学家。他一生致力科学事业,成果颇多。 
     有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布。 
     有一次闲暇时,他提出过一个有趣的问题,后称为:“泊松分酒”。 
     在我国古代也提出过类似问题,遗憾的是没有进行彻底探索,其中流传较多是:“韩信走马分油”问题。 
     有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 
     每一行表示一个操作过程中的油量状态。 
     注意: 
     请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分! 
     请把所有类写在同一个文件中,调试好后,存入与【考生文件夹】下对应题号的“解答.txt”中即可。 
     相关的工程文件不要拷入。 
     请不要使用package语句。 
     源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。   
     */
    import java.util.Scanner;
    
    public class 泊松分酒 {
    	// 有6种倒酒方法,x[0]->y[0]即("0"->"1")代表第一个瓶子向第二个瓶子倒酒,后即同理
    	static int[] x = { 0, 1, 2 }; // 0 为第一个瓶子,1为第二个瓶子 ,2为第三个瓶子
    	static int[] y = { 1, 2, 0 };
    	static int[][] rr = new int[1000][3]; // 记录倒酒后每一行结果
    	static int index = 0;
    	static int count = 0;
    	static int[] tt = { 0, 0, 0 };
    
    	// 输入数据
    	public static int[] input() {
    		Scanner scan = new Scanner(System.in);
    		String[] s = scan.nextLine().split(",");
    		int[] temp = new int[s.length];
    		for (int i = 0; i < s.length; i++) { // 字符转为数字
    			temp[i] = Integer.parseInt(s[i]);
    		}
    		return temp;
    	}
    
    	// 输出
    	public static void print(int[][] rr) {
    		for (int i = 0; i < index; i++) {
    			for (int j : rr[i])
    				System.out.print(j + "	");
    			System.out.println();
    		}
    		System.out.println("记录数:(" + index + ")");
    	}
    
    	// 记录步骤
    	public static void record(int[] cur) {
    		rr[index][0] = cur[0];
    		rr[index][1] = cur[1];
    		rr[index][2] = cur[2];
    		index++;
    	}
    
    	// 判断当前的记录 是否 在以前的记录里 存在
    	public static boolean curExist(int[] cur) {
    		for (int i = 0; i < index; i++) {
    			if (rr[i][0] == cur[0] && rr[i][1] == cur[1] && rr[i][2] == cur[2]) {
    				return true;
    			}
    		}
    		return false;
    	}
    
    	// 倒酒
    	public static void pour(int[] v, int[] cur, int i) {
    		count++; // 统计倒酒的次数, 若倒酒次数超过1000次,则识为"不可能"
    		int r = v[y[i]] - cur[y[i]]; // 计算 y瓶中还可以装入多少酒,拿y瓶的总容量-y瓶当前的酒
    		if (cur[x[i]] > r) { // x > y 时
    			cur[y[i]] = v[y[i]]; // y = 满
    			cur[x[i]] -= r; // x = x - r
    		} else { // x <= y
    			cur[y[i]] += cur[x[i]]; // y = y + x
    			cur[x[i]] = 0; // x = x - r
    		}
    	}
    
    	// 求解
    	public static void f(int[] v, int[] cur, int m) {
    		if (m > v[0]) {
    			System.out.println("要求得到的油量" + m + "大于最大容器" + v[0] + ",所以
    不可能");
    			return;
    		}
    		boolean flag = true;
    		record(cur);
    		while (flag) {
    			if (count > 1000) {
    				System.out.println("倒酒次数超过1000次,所以
    不可能");
    				return;
    			}
    			for (int i = 0; i < 3; i++) { // 3种倒酒方法
    				// 找到解,退出
    				if (cur[0] == m || cur[1] == m || cur[2] == m) {
    					print(rr); // 找到解,输出记录
    					flag = false;
    					break;
    				}
    				// 如果 x 瓶中为空,则跳过, 执行下一轮倒酒
    				if (cur[x[i]] == 0) {
    					continue;
    				}
    				pour(v, cur, i);// 倒酒
    				// 记录步骤
    				if (curExist(cur)) {
    					cur[0] = rr[index - 1][0]; // 还原为上次倒酒的值
    					cur[1] = rr[index - 1][1];
    					cur[2] = rr[index - 1][2];
    					// --index;
    					continue;
    				} 
    				else {
    				  record(cur);
    				}
    
    			}
    		}
    	}
    
    	// 主函数
    	public static void main(String[] args) {
    		System.out.println("输入数据(格式为7个数字用","号隔开,例:)12,8,5,12,0,0,6");
    		int[] t = input(); // 输入数据
    		int[] v = { t[0], t[1], t[2] }; // 每个容器的最大容量 v
    		int[] cur = { t[3], t[4], t[5] }; // 容器的开始的状态 init
    		int m = t[6]; // 要求得到的油量 r
    		f(v, cur, m);
    	}
    }
    输入数据(格式为7个数字用","号隔开,例:)12,8,5,12,0,0,6
    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	
    记录数:(7)
    



  • 相关阅读:
    DevExpress的TreeList实现节点上添加自定义右键菜单并实现删除节点功能
    C#中全局作用域的常量、字段、属性、方法的定义与使用
    DevExpress的TreeList的常用属性设置以及常用事件
    DevExpress的TreeList怎样设置数据源,从实例入手
    一、ABP框架框架摘要
    十、LINQ查询之延迟执行
    一、
    二、core abp 数据库迁移
    十一、ASP.NET Boilerplate
    十、ABP
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3143011.html
Copyright © 2020-2023  润新知