猫の空 2023-03-10 16:37 采纳率: 0%
浏览 23

关于#屋顶铺设瓦片#的算法,如何解决?

有一个算法上的问题各位同学帮助下

img

在屋顶上铺设瓦片,瓦片的话有不同宽度,假设长度分别为1500mm,2000mm,3000mm等(不固定)等不同的瓦片, 屋顶的长度是16300cm(暂时不考虑宽度), 要求如下

  1. 铺设玩的瓦片总宽度超过屋顶长度86mm但又不能超过屋顶长度的1000mm
  2. 优先选择长的瓦片来铺设,也就是在如上情况下,优先把3000mm的铺上,再去铺次宽的
  3. 剩余最后若有更短的选择,为了节约成本,选择更短的
    现在我的代码如下
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;

import lombok.Data;

public class test {
    // 瓦片限制最小值
    private static final Integer MIN = 86;
    // 瓦片限制最大值
    private static final Integer MAX = 1000;

    private static List<TileDTO> list = new ArrayList<>();

    static {
        list.add(new TileDTO(1500));
        list.add(new TileDTO(2000));
        list.add(new TileDTO(3000));
    }

    public static void main(String[] args) {
        System.err.println(get(list, 16300));
    }

    /**
     * 
     * @param list        瓦片数组
     * @param totalLength 屋顶总长度
     * @return
     */
    public static List<TileDTO> get(List<TileDTO> list, Integer totalLength) {
        List<TileDTO> guideRailDTOs = new ArrayList<>(list.size());
        if (CollectionUtils.isEmpty(list)) {
            throw new RuntimeException("瓦片数组为空");
        }
        // 倒序
        list = list.stream().sorted(Comparator.comparing(TileDTO::getLength).reversed())
                .collect(Collectors.toList());
        // 获取最短瓦片长度
        Integer shortest = list.get(list.size() - 1).getLength();
        if (shortest - totalLength > MAX) {
            throw new RuntimeException(String.format("最短瓦片长度不能超过总长度%dmm!", MAX));
        }
        // 最大限制总长
        totalLength += MAX;
        for (int i = 0; i < list.size(); i++) {
            // 当前瓦片
            TileDTO tileDTO = list.get(i);
            // 当前瓦片长度
            Integer length = tileDTO.getLength();
            // 当前瓦片数量
            Integer quantity = 0;
            // 若当前剩余长度大于1000, 并且当前瓦片长度小于等于当前剩余长度
            if (length <= totalLength) {
                // 计算出数量,取商
                quantity = (int) (totalLength / length);
                // 计算出剩余长度
                totalLength -= quantity * length;
                // 计算出比当前长度稍短一些的长度
                if (i != list.size() - 1 && (totalLength > MAX || MAX < MIN + totalLength)
                        && totalLength <  list.get(i + 1).getLength()) {
                    // 将当前瓦片数量减一
                    quantity -= 1;
                    // 当前剩余长度加上去
                    totalLength += length;
                }
            }
            guideRailDTOs.add(new TileDTO(tileDTO.getLength(), quantity));
        }
        return guideRailDTOs;
    }

    @Data
    static class TileDTO {

        /**
         * 瓦片长度
         */
        private Integer length;

        /**
         * 使用瓦片数量
         */
        private Integer quantity;

        public TileDTO(Integer length) {
            this.length = length;
        }

        public TileDTO(Integer length, Integer quantity) {
            this.length = length;
            this.quantity = quantity;
        }
    }

}


但是现在根据我们的代码算出的结果是
3000x5+2000x1

这个结果是有瑕疵的,因为根据我们的最优策略正确答案是 3000x5+1500x1(因为比起2000, 1500符合最优成本)
所以现在请各位同学帮忙看下,我这边算法需要在哪里进行优化

  • 写回答

1条回答 默认 最新

  • chenshanshan128 2023-03-10 16:59
    关注

    根据您的代码和要求,您需要做出以下调整:

    1.计算出最短的瓦片长度shortest,如果shortest超过MAX或者shortest - totalLength > MAX,则应该抛出异常。

    2.在for循环中,如果当前剩余长度小于等于MAX,直接退出循环,因为此时无论如何也不能再使用更长的瓦片了。

    3.在for循环中,如果当前剩余长度大于MAX,但是当前瓦片长度小于等于MAX,应该尝试使用更短的瓦片来填充剩余长度,这样才能保证成本最优。

    下面是修改后的代码:

    java
    Copy code
    public static List<TileDTO> get(List<TileDTO> list, Integer totalLength) {
        List<TileDTO> guideRailDTOs = new ArrayList<>(list.size());
        if (CollectionUtils.isEmpty(list)) {
            throw new RuntimeException("瓦片数组为空");
        }
        // 倒序
        list = list.stream().sorted(Comparator.comparing(TileDTO::getLength).reversed())
                .collect(Collectors.toList());
        // 获取最短瓦片长度
        Integer shortest = list.get(list.size() - 1).getLength();
        if (shortest > MAX || shortest - totalLength > MAX) {
            throw new RuntimeException(String.format("最短瓦片长度不能超过总长度%dmm!", MAX));
        }
        // 最大限制总长
        totalLength += MAX;
        for (int i = 0; i < list.size(); i++) {
            // 当前瓦片
            TileDTO tileDTO = list.get(i);
            // 当前瓦片长度
            Integer length = tileDTO.getLength();
            // 当前瓦片数量
            Integer quantity = 0;
            // 若当前剩余长度大于1000, 并且当前瓦片长度小于等于当前剩余长度
            if (length <= totalLength) {
                // 计算出数量,取商
                quantity = (int) (totalLength / length);
                // 计算出剩余长度
                totalLength -= quantity * length;
                // 如果当前剩余长度小于等于MAX,直接退出循环
                if (totalLength <= MAX) {
                    break;
                }
                // 如果当前剩余长度大于MAX,但是当前瓦片长度小于等于MAX,
                // 尝试使用更短的瓦片来填充剩余长度,保证成本最优
                if (i != list.size() - 1 && totalLength > list.get(i + 1).getLength() && length <= MAX) {
                    for (int j = i + 1; j < list.size(); j++) {
                        Integer shorterLength = list.get(j).getLength();
                        if (shorterLength <= MAX && totalLength > shorterLength) {
                            int shorterQuantity = (int) (totalLength / shorterLength);
                            if (shorterQuantity > 0) {
                                quantity -= 1;
                                totalLength += length;
                                quantity += shorterQuantity;
                                totalLength -= shorterQuantity * shorterLength;
                                break;
                            }
                        }
                    }
                }
            }
            guideRailDTOs
    
    
    评论

报告相同问题?

问题事件

  • 修改了问题 3月13日
  • 专家修改了标签 3月12日
  • 创建了问题 3月10日

悬赏问题

  • ¥15 请问Ubuntu要怎么安装chrome呀?
  • ¥15 视频编码 十六进制问题
  • ¥15 Xsheii7我安装这个文件的时候跳出来另一个文件已锁定文件的无一部分进程无法访问。这个该怎么解决
  • ¥15 unity terrain打包后地形错位,跟建筑不在同一个位置,怎么办
  • ¥15 FileNotFoundError 解决方案
  • ¥15 uniapp实现如下图的图表功能
  • ¥15 u-subsection如何修改相邻两个节点样式
  • ¥30 vs2010开发 WFP(windows filtering platform)
  • ¥15 服务端控制goose报文控制块的发布问题
  • ¥15 学习指导与未来导向啊