/*
泊松是法国数学家、物理学家和力学家。他一生致力科学事业,成果颇多。
有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布。
有一次闲暇时,他提出过一个有趣的问题,后称为:“泊松分酒”。
在我国古代也提出过类似问题,遗憾的是没有进行彻底探索,其中流传较多是:“韩信走马分油”问题。
有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 Demo16 {
// 有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+"\t");
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]+",所以\n不可能");
return;
}
boolean flag = true;
record(cur);
while(flag){
if(count>1000){
System.out.println("倒酒次数超过1000次,所以\n不可能");
return;
}
for(int i=0; i<3; i++){ // 6种倒酒方法
// 找到解,退出
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)