好的,这就是我要做的事情
作为MCI(Mammoth Cakes Incorporated)的员工,创造极大的作品是您的职责 分层生日蛋糕。一个分层的生日蛋糕是通过采取小圆形蛋糕层和 将它们堆叠在一起。
为了完成工作,你站在一条大传送带前面 而不同大小的层在你面前经过。当你看到一个你喜欢的,你可以把它拿走 传送带,并将其添加到您的蛋糕。
您可以根据需要为蛋糕添加任意数量的图层, 只要你遵守这些规则:
将一个图层添加到蛋糕后,就无法移动。 (它弄乱了结冰。)因此,层次 只能添加到你的蛋糕顶部。
每一层只在你面前经过一次。你可以接受或离开它。如果你接受它,你 必须将它添加到你的蛋糕顶部。如果你离开它,它会沿传送带向下移动, 永远不会回来。
蛋糕中的每一层必须至少与下面的图层一样小。你不能放置一个 较小的一层上面的较大层。
您将被提前告知传送带下层的直径(以英寸为单位)。 你的工作是使用这些层创建最高的蛋糕。 例如,假设以下列表表示下降的层的直径 传送带:8 16 12 6 6 10 5
假设您为蛋糕取第一层(直径为8英寸)。这意味着您可能不会采用第二层(因为您已经有一个8“的图层,而16”> 8“)。同样,你不能 采取第三层,但你可以采取第四层(从6“< 8”)。
之后,你可以 也采取第五层(规则只是顶部的层不能更大;它可以是相同的 尺寸)。以这种方式进行,我们可以制作一个高度为4层的蛋糕:8 6 6 5 但是,如果我们让第一层继续并从第二层开始,我们可以创建一个 蛋糕的高度为5:16 12 6 6 5
您的程序将处理多个输入集,每行一个。每一行都以整数N开头, 接着是N个正整数,按照它们的顺序表示蛋糕层的大小 到达传送带。 N将始终为非负整数,0 N 100,000。每一层 直径在1到100,000之间(含)。 N = 0的一行表示结束 输入
Sample Input
7 8 16 12 6 6 10 5
10 45 25 40 38 20 10 32 25 18 30
10 10 9 8 7 6 5 4 3 2 1
0
Sample Output
5
6
10
问题:找到最高层的蛋糕
这是我到目前为止所写的内容:
import java.io.*;
import java.util.*;
public class cake
{
private static String line;
private static ArrayList storage = new ArrayList();
private static Integer highestStack = 0;
public static void main(String [] args)throws IOException
{
FileReader fin = new FileReader("cake.in");
BufferedReader infile = new BufferedReader(fin);
FileWriter fout = new FileWriter("cake.out");
BufferedWriter outfile = new BufferedWriter(fout);
line = infile.readLine();
do
{
String[] temp = line.split(" ");
String number;
for(int j = temp.length-1; j!=0; j--)
{
if(Integer.parseInt(temp[j]) <= Integer.parseInt(temp[j-1]))
{
highestStack++;
}
}
storage.add(highestStack);
// Collections.sort(storage);
line = infile.readLine();
}while(!line.equals("0"));
infile.close();
outfile.close();
}
}
答案 0 :(得分:2)
正如我评论几个完全忽略了这一点的答案,这是一个动态规划问题。
现在您已经添加了约束,很明显,在 O(n ^ 2)中运行的动态编程解决方案是可行的方法,并且N不会超过100的事实000使用DP可以很容易地解决(使用非DP算法可能很难解决)。
每时每刻,你都要问自己“我能做的最好的事情是'x'”。
以下是第一个例子的样子:
0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 (Best we can do using pieces: 5 )
0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 (Best we can do using pieces: 5 10 )
0 0 0 0 0 1 2 2 2 2 2 2 2 2 2 2 2 (Best we can do using pieces: 5 10 6 )
0 0 0 0 0 1 3 3 3 3 3 3 3 3 3 3 3 (Best we can do using pieces: 5 10 6 6 )
0 0 0 0 0 1 3 3 3 3 3 3 4 4 4 4 4 (Best we can do using pieces: 5 10 6 6 12 )
0 0 0 0 0 1 3 3 3 3 3 3 4 4 4 4 5 (Best we can do using pieces: 5 10 6 6 12 16 )
0 0 0 0 0 1 3 3 4 4 4 4 4 4 4 4[5] (Best we can do using pieces: 5 10 6 6 12 16 8 )
Tallest cake as a height of: 5
阅读上面一行的方法很简单。我们以第一行为例:
0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
这意味着我们可以制作的最高蛋糕,其基数为5到16,由一个元素组成(我们的第一个元素,'5')。
然后我们得到了'10'的片段,我们得到了这句话:
0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2
这意味着我们可以从5到9制作的最高蛋糕将有一个元素(我们的'5'),从10到16我们可以填充两个元素(5和10)。
如果你愿意,你可以这样重复,最多可以有10万个元素。
在我的计算机上,完整的100 000解决方案使用动态编程只需不到20秒即可解决。
这是解决问题并输出上述内容的代码。我故意添加输出语句,以便您可以看到正在发生的事情(只有相对较小的数字才能看起来非常漂亮,这只是为了得到算法的结果)。
public static void main( String[] args ) {
doIt( new int[] {8,16,12,6,6,10,5} );
doIt( new int[] {0, 45, 25, 40, 38, 20, 10, 32, 25, 18, 30} );
doIt( new int[] {10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1} );
}
public static void doIt( int[] r ) {
final int[] a= new int[r.length];
int max = Integer.MIN_VALUE;
for (int i = 0; i < a.length; i++) {
max = Math.max( max, a[i] );
a[(a.length-1)-i] = r[i];
}
final int[] s = new int[max+1];
for (int i = 0; i < a.length; i++) {
final int size = a[i];
s[size]++;
for (int j = size+1; j < s.length; j++) {
s[j] = Math.max( s[j-1], s[j] );
}
for (int j = 0; j < s.length; j++) {
System.out.print( " " + ((s[j]) > 9 ? "" : " ") + s[j] );
}
System.out.print( " (Best we can do using pieces: " );
for (int k = 0; k <= i; k++) {
System.out.print( a[k] + " " );
}
System.out.println( ")" );
}
System.out.println( "Tallest cake as a height of: " + s[s.length-1] );
}
答案 1 :(得分:1)
我不确定你在问什么,确切地说......所以,我会给你一些一般性的提示。
查看Stack数据结构,而不是ArrayList。 将一个图层推入堆栈,然后使用 peek 检查蛋糕堆最顶层的直径与传送带中的当前项目的对比。
如果目标是找到最高的蛋糕,一个天真的方法是简单地应用上述算法,从输送机的第一层开始,一直到最后,并记录最终高度(堆栈.size()的)。然后重复输送机中的第二项作为基础,然后是第三项,依此类推,将结果高度与每次循环结束时记录的最大值进行比较。
答案 2 :(得分:1)
这个输入序列很棘手:
10 45 25 40 38 20 10 32 25 18 30
只是跳过引入层的简单方法会找到这些[蛋糕]:
[10] 45 25 40 38 20 10 32 25 18 30
10 [45 25] 40 38 20 10 32 25 18 30
10 45 [25] 40 38 20 10 32 25 18 30
10 45 25 [40 38 20 10] 32 25 18 30 <-- naive tallest, 4
10 45 25 40 [38 20 10] 32 25 18 30
10 45 25 40 38 [20 10] 32 25 18 30
10 45 25 40 38 20 [10] 32 25 18 30
10 45 25 40 38 20 10 [32 25 18] 30
10 45 25 40 38 20 10 32 [25 18] 30
10 45 25 40 38 20 10 32 25 [18] 30
10 45 25 40 38 20 10 32 25 18 [30]
游戏规则允许你跳过任何一层,不仅仅是主要的层,所以在这种情况下正确的最高蛋糕将是:
10 [45] 25 [40] [38] 20 10 [32] [25] [18] 30
或仅使用所选图层写出:
45 40 38 32 25 18
答案 3 :(得分:1)
您尝试解决的问题是动态编程问题(尽管很简单)。
public static int findMaxHeight(int[] layers) {
int[] max = new int[layers.length];
for(int i=layers.length - 1; i >= 0; i--) {
int localMax = 0;
for(int j=0; j < layers.length; j++) {
if(layers[j] < layers[i]) {
if(max[j] > localMax) {
localMax = max[j];
}
}
}
max[i] = localMax + 1;
}
int height = 0;
for(int i=0; i < max.length; i++) {
if(max[i] > height) {
height = max[i];
}
}
return height;
}
作为其工作原理的一步,请考虑:
8 16 12 6 6 10 5
由于我们的顺序相反,
5 10 6 6 12 16 8
从5开始,[]:
的值小于55 10 6 6 12 16 8
1
从[5]开始,max [5] = 1所以1 + 1
5 10 6 6 12 16 8
1 2
等等......
5 10 6 6 12 16 8
1 2 2 3 4 5 4
然后我们找出列表的最大值[1,2,2,3,4,5,4],即5。
并且,如上所述,这是他在问题描述中介绍的所提供示例的正确答案。
算法的工作原理是保存每层的最大值。问题解释说,对于任何给定的层,它只能堆叠小于或等于其直径的蛋糕。因此,任何给定层的最大值始终是在带上加上1的相等或更小尺寸的层的最大值(计算层本身)。如果没有可堆叠的图层,我们知道该图层的最大值为1。
答案 4 :(得分:1)
让我们来看看这个过程。每次我们在装配线上遇到一个图层时,我们都会做出决定:是否使用此图层?总体上最好的结果是以下两个结果中的更好结果:
我们使用这个图层,并在其上构建最高的蛋糕,使用剩余的不大于此图层
我们不使用此图层,并使用任何其余图层构建最高的蛋糕。
我们可以使用递归 - 伪代码
简单地对此进行建模tallest(remaining_layers, base_size) = # set base_size = infinity the first time
max(
first_layer + tallest(other_layers, size(first_layer)),
tallest(other_layers, base_size)
)
where first_layer = first(remaining_layers),
other_layers = rest(remaining_layers)
然而,由于我们应该使用动态编程,因此不会自行削减它。
我们的想法是,我们两次以tallest
递归调用other_layers
。如果我们可以召唤一次并获得我们需要的所有信息,那不是很好吗?
我们需要哪些信息?好吧,如果我们用任何基本尺寸的剩余层使用最高的蛋糕,我们将设置:我们只选择适合当前图层的最高蛋糕,看看是否有改善与总体最高的蛋糕。但这就是诀窍:即使它没有改进,我们仍然可以获得信息。我们的想法是列出每种尺寸最“有效”(最小的基础)蛋糕。
因此,我们的流程如下:
Set up a list of cakes, with one cake in it that has zero layers.
# There will be, at all times, one cake in the list of any given height.
# Starting at zero instead of one makes the iteration neater.
For each layer on the conveyor belt, working **backwards** from the last:
Find the tallest cake in the list that fits on this layer.
Construct the cake 'c' consisting of that cake on top of this layer.
If there is already a cake in the list of the same height as 'c':
If the other cake has a smaller base, throw 'c' away. # It didn't help.
Otherwise, remove the other cake from the list. # 'c' is better.
If we still have 'c', add it to the list.
The tallest possible cake for the input is now the tallest one in the list.
答案 5 :(得分:0)
实际上很简单,就是这样:
int[] layers = new int[] {x1,x2,x3...xn};
int[] count = new int[layers.length];
for(int i = 1; i < layers.length; i++)
{
for(int j = i+1 ; j < layers.length; j++)
{
if ( layers[j] >= layers[i]) count[i]++;
}
}
answer = Collections.max(Arrays.asList(count));