[DP] 堆盒子问题

给一堆盒子,知道每个盒子的三围(长宽高),盒子正面朝你,不能旋转摆放,按照大的放在小的下面的原则堆起来,必须是 strictly larger,同样大小的盒子不行,问怎么样堆到最大的高度?

思路:动态规划 

最优解一定是 max( {box_1 be the bottom}, {box_2 be the bottom}, ... , {box_n be the bottom} ),所以我们遍历所有的 box, 把每个box作为底部构建subproblem。

按说在subproblem {box_1 be the bottom}中,box candidates 中不能再有box_1,因为它已经用作底部了,所以遍历的时候理应跳过 box_1,然而这样会大大增加题目的复杂性。

幸好这道题有特殊的地方:strictly better, 如果 box_1 已经是底部了,那么即使它在 candidates 中再次出现也不会被选中,就不会产生问题。

代码:

package chapter9;

import java.util.ArrayList;
import java.util.HashMap;

public class P10_book_ {

    
    public ArrayList<Box> createStack(Box[] boxes){
        return createStackR(boxes, null, new HashMap<Box, ArrayList<Box>>());
    }
    
    public ArrayList<Box> createStackR(Box[] boxes, Box bottom, 
            HashMap<Box, ArrayList<Box>> stackMap){
        
        if(stackMap.containsKey(bottom))
            return stackMap.get(bottom);
        
        ArrayList<Box> bestStack = new ArrayList<Box>();
        int bestHeight = 0;
        
        for(Box b : boxes){
            if(b.canBeAbove(bottom)){
                ArrayList<Box> newStack = createStackR(boxes, b, stackMap);
                int newHeight = stackHeight(newStack);
                
                if(newHeight > bestHeight){
                    bestHeight = newHeight;
                    bestStack = newStack;
                }
            }
        }
        
        // make a copy of bestStack before modify it
        bestStack = (ArrayList<Box>)bestStack.clone();
        
        if(bottom != null)
            bestStack.add(bottom);
        
        stackMap.put(bottom, bestStack);
        return bestStack;
    }
    
    
    
    public int stackHeight(ArrayList<Box> stack){
        
        if(stack == null || stack.isEmpty())
            return 0;
        
        int totalHeight = 0;
        for(Box b : stack){
            totalHeight += b.height;
        }
        return totalHeight;
    }
    
}

class Box{
    
    int width;
    int height;
    int depth;
    
    public boolean canBeAbove(Box box){
        if(box == null)
            return true;
        
        if(width < box.width && height < box.height && depth < box.depth){
            return true;
        }
        
        return false;
    }
}

 

posted @ 2014-06-14 11:14  门对夕阳  阅读(662)  评论(0编辑  收藏  举报