今天看一个分油的题目,来了兴趣,所以忍不住解一下.
原题
分油算法:一个桶中有12斤油,要求倒出6斤,可现在另外只有两个桶,分别可装8斤与5斤,请问应如何来倒?
补充:这里的12,6,8,5都是变量,应该可以自己设置,输出是每一次分油的步骤。
这里是用java,用过程语言也行,把实例变量用全局变量替换就好了.
这个问题有时候是无解的, 比如 25, 9 (要倒出来的油) ,8,5
无解的情况,稍微分析了一下,没有发现规律.
其实挺简单的,穷举递归.
MAXDEEP 超过21 之后 算法的时间就是分钟级的了,但是真有解的话,最优步长一般不超过15,一般是4 ~ 8.
有解需满足以下两个条件之一,没有经过验证,这可能会是一道有趣的数学题目.
如果要倒出的油在两个空桶的容量之间,或者小于总油量减去空桶的容量就会解
希望有兴趣的的朋友也尝试一下,看有没有更好和更确定的算法.
public class AllocateOil {
private int capicity_x;
private int capicity_y;
private int capicity_z;
private int goal;
private int minDeep;
public static int MAXDEEP = 20;
private String stepExplain="Not Feasible";
public AllocateOil(int x,int y,int z, int goal){
capicity_x = x;
capicity_y = y;
capicity_z = z;
this.goal = goal;
minDeep = MAXDEEP + 1;
}
public void allocate(int volumn_x,int volumn_y,int volumn_z,int deep,String stepExplain,int flag){
if (deep >= Math.min(minDeep, MAXDEEP) ) return;// only procee limited deep and got optimization method;
int space_x = capicity_x - volumn_x;
int space_y = capicity_y - volumn_y;
int space_z = capicity_z - volumn_z;
stepExplain = stepExplain + "/n" + "x:" + volumn_x + ", y:" +volumn_y + ", z:" +volumn_z;
if(volumn_x == goal ||volumn_y == goal ||volumn_z == goal ){
if(deep < minDeep){
this.stepExplain = stepExplain;
minDeep = deep;
}
return;
}
// exchage X and Y
if (volumn_x > 0 && space_y >0 && flag != -1 )
allocate(volumn_x>space_y?volumn_x - space_y:0,volumn_x>space_y?capicity_y:volumn_x + volumn_y,volumn_z,deep + 1,stepExplain + "; x -> y ; step " + deep , 1);
if (volumn_y > 0 && space_x >0 && flag != 1 )
allocate(volumn_y>space_x?capicity_x:volumn_x + volumn_y,volumn_y>space_x?volumn_y - space_x:0,volumn_z,deep + 1,stepExplain + "; y -> x ; step " + deep , -1);
// exchage X and Z
if (volumn_x > 0 && space_z >0 && flag != -2 )
allocate(volumn_x>space_z?volumn_x - space_z:0,volumn_y,volumn_x>space_z?capicity_z:volumn_x + volumn_z,deep + 1,stepExplain + "; x -> z ; step " + deep , 2);
if (volumn_z > 0 && space_x >0 && flag != 2 )
allocate(volumn_z>space_x?capicity_x:volumn_x + volumn_z ,volumn_y,volumn_z>space_x?volumn_z - space_x:0,deep + 1,stepExplain + "; z -> x ; step " + deep , -2);
// exchage Y and Z
if (volumn_y > 0 && space_z >0 && flag != -3 )
allocate(volumn_x,volumn_y>space_z?volumn_y - space_z:0,volumn_y>space_z?capicity_z:volumn_y + volumn_z,deep + 1,stepExplain + "; y -> z ; step " + deep , 3);
if (volumn_z > 0 && space_y >0 && flag != 3 )
allocate(volumn_x,volumn_z>space_y?capicity_y:volumn_y + volumn_z,volumn_z>space_y?volumn_y - space_z:0,deep + 1,stepExplain + "; z -> y ; step " + deep , -3);
}
public void allocate(){
this.allocate(this.capicity_x,0,0,0,"",9);
System.out.println(stepExplain);
}
public static void main(String[] args){
AllocateOil alocOil = new AllocateOil(55,11,5,40);
alocOil.allocate();
}
}
-----------------------------------------------------------
x:55, y:0, z:0; x -> z ; step 0
x:50, y:0, z:5; z -> y ; step 1
x:50, y:5, z:0; x -> z ; step 2
x:45, y:5, z:5; z -> y ; step 3
x:45, y:10, z:0; x -> z ; step 4
x:40, y:10, z:5