这个问题是在论坛上提出的。有什么建议吗?
金字塔有一个杯子在水平,2个在2级,3个在3级,依此类推。 它看起来像这样
1 2 3 4 5 6
每个杯子都有容量C.你从顶部倒入L升水。当杯子1被填满时,它同样地溢出到2,3杯,当它们被填满时,杯子4和6仅从2和3获得水,但是5从两个杯子获得水,依此类推。 现在给出C和L。找到第i个杯子中的水量?
答案 0 :(得分:8)
每个玻璃杯中都有进水流量,水量,可能还有一些流出(溢出)。
如果每个玻璃杯可以包含1个单位的水,并且您倒入15个单位的水,则会得到以下结果(括号中的溢出量):
Incoming flow = 15, capacity = 1
Level 1: 1(14)
Level 2: 1(6) 1(6)
Level 3: 1(2) 1(5) 1(2)
Level 4: 1(1) 1(2.5) 1(2.5) 1(1)
Level 5: 1 1(0.75) 1(1.5) 1(0.75) 1
Level 6: 0 0.375 1(0.125) 1(0.125) 0.375 0
Level 7: 0 0 0.0625 0.125 0.0625 0 0
第一级的传入流是L. c
级r
上的传入流是Fin(c, r)
,可以写成:
Fin(0, r) = 0
Fin(r+1, r) = 0
Fin(1, 1) = L
Fin(c, r) = Fout(c - 1, r - 1)/2 + Fout(c, r - 1)/2
该玻璃杯中的水量是:
A(c, r) = Min(C, Fin(c, r))
传出流程是:
Fout(c, r) = Max(0, Fin(c, r) - C)
我没有看到任何明显的公式来评估A(c, r)
,而不是递归地进行。{/ p>
要从索引到行和玻璃位置,您可以执行以下操作:
index = r*(r-1)/2 + c
r = floor((1 + sqrt(8*index - 7))/2)
c = index - r*(r-1)/2
(indexes start with 1)
答案 1 :(得分:0)
一些想法: (1)重要的是知道哪两个杯子是第二杯的输入。 (2)重要的是要知道从左侧带水的最小Lleft以及Lright从右侧带水的水平 (3)所以你需要知道哪些杯子给杯子提供水。如果从0开始编号,这更容易,快速思考。杯ith将填充(i-1)* 2 + 1和i * 2,这意味着杯子kth将从(k%2 = 1)接收水( k-1)/ 2和(k + 1)/ 2(对于k%2 = 0)k / 2和k / 2 + 1 (4)对此你应该检查任何L你将计算差异L-Lleft和L-Lright。当阳性时,所提供的水是除以计算差值的2 ^ n的结果,其中n是杯子的水平。
答案 2 :(得分:0)
如果您将金字塔建模为图形,则问题将转换为广度优先搜索。在遍历每个节点时,获取其邻居并存储其溢出数量。如果前一节点已经检索到邻居(这将在5节点的情况下发生,因为节点2和节点3具有边缘),则必须根据其容量和已填充的内容更新溢出(节点2;假设节点2在节点3之前遍历。)
答案 3 :(得分:0)
用于计算二项式系数的pascal三角形解可用于解决该问题。我们只需稍微调整算法,而不是计算二项式系数,我们计算水位。给定ith杯,我们计算水平和指数,以找出杯子在三角形中的位置。
杯子被建模为
0 Level 1
1 2 Level 2
3 4 5 Level 3
getIndex()和getLevel()返回索引和级别。索引和级别从1开始。
public static int getIndex(int i) {
int totalNodes = i + 1;
double d = (-3 + Math.sqrt(9 - 8*(1-totalNodes)))/2;
int level = (int)Math.floor(d);
int total = ((level+1)*(level+2))/2;
int index = 0;
if(total==totalNodes) index = level;
else{
level++;
index = totalNodes - total - 1;
}
return ++index;
}
public static int getLevel(int i) {
int totalNodes = i + 1;
double d = (-3 + Math.sqrt(9 - 8*(1-totalNodes)))/2;
int level = (int)Math.floor(d);
int total = ((level+1)*(level+2))/2;
int index = 0;
if(total==totalNodes) index = level;
else{
level++;
index = totalNodes - total - 1;
}
return ++level;
}
k是从0开始的第k个杯子.C是杯容量,L是总水量。
public static double getWaterLevel(double C, double L, int k) {
int n = getLevel(k);
int index = getIndex(k);
double[] water = new double[index+1];
water[1] = L;
for(int i = 2; i <= n; i++)
{
boolean overflowed = false;
for(int j = Math.min(i, index); j > 0; j--) {
double over = 0;
if(water[j]>C) over = (water[j]-C)/2;
if(water[j-1]>C) over += (water[j-1]-C)/2;
water[j] = over;
if(!overflowed && over!=0) overflowed=true;
}
if(!overflowed) break; // no more overflow. stop
}
return water[index] > C ? C : water[index];
}
答案 4 :(得分:0)
这是另一种简单的解决方案,只需将水倒入当前的玻璃杯中,然后检查是否有多余的水然后流到下一个水位。在这里,我使用了2D Mat来倒水。然后,我将2D垫转换为尺寸等于ith元素/玻璃的1D,我们需要返回并返回该值。明智地实施,这是一个非常简单的解决方案。
private double fillWaterInGlasses(double capacity, double water , int glassToFind) {
int maxLevel = (int)(water/capacity)/2 + 1;
double[][] glasses = new double[maxLevel][maxLevel];
// Pour total water in top glass initially.
glasses[0][0] = water;
int level=0;
boolean waterInLevel = true;
while(waterInLevel) {
waterInLevel = false;
// For each glass in the level.
for(int j=0; j<=level; j++) {
// If the glass has more liquid then it can store then pour it to glasses under it.
if(glasses[level][j] > capacity) {
double extraWater = glasses[level][j] - capacity;
glasses[level][j] = capacity;
glasses[level+1][j] += extraWater / 2;
glasses[level+1][j+1] += extraWater / 2;
waterInLevel = true;
}
}
level++;
}
double res[] = new double[glassToFind];
int k =0;
for (int i = 0; i < glasses.length; i++) {
for (int j = 0; j <= i; j++) {
res[k] = glasses[i][j];
if (k == glassToFind-1){
return res[glassToFind-1];
}
k++;
}
}
return res[glassToFind-1];
}
答案 5 :(得分:-1)
这是一个简单易懂的实现:
public class main {
static float total_water = 50;
static int N = 20;
static glass[][] pyramid = new glass[N][N];
public static void main(String[] args) {
build_pyramid();
pour_water(0, 0, total_water);
print_pyramid();
print_total_water_stored();
}
private static void print_total_water_stored() {
float total = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j <= i; j++)
total += pyramid[i][j].filled;
}
System.out.println("total water stored= " + total);
}
private static void pour_water(int row, int col, float water) {
if (water >= (pyramid[row][col].capacity - pyramid[row][col].filled)) {
water -= (pyramid[row][col].capacity - pyramid[row][col].filled);
pyramid[row][col].filled = pyramid[row][col].capacity;
pour_water(row + 1, col, water / 2);
pour_water(row + 1, col + 1, water / 2);
} else {
pyramid[row][col].filled += water;
}
}
public static void build_pyramid() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
pyramid[i][j] = new glass(1);
}
}
public static void print_pyramid() {
for (int i = 0; i < N; i++) {
for (int j = 0; j <= i; j++)
System.out.print(pyramid[i][j].filled + " ");
System.out.println();
}
}
}
class glass {
float capacity;
float filled;
glass(float cap) {
capacity = cap;
filled = 0;
}
}