892. Surface Area of 3D Shapes*

本文介绍了一种高效计算三维网格上放置的1x1x1立方体总表面积的方法。通过分析每个立方体贡献的面积,并减去相邻立方体间重叠的面积,实现了对LeetCode题目892.SurfaceAreaof3DShapes的解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

892. Surface Area of 3D Shapes*

https://leetcode.com/problems/surface-area-of-3d-shapes/

题目描述

On a N * N grid, we place some 1 * 1 * 1 cubes.

Each value v = grid[i][j] represents a tower of v cubes placed on top of grid cell (i, j).

Return the total surface area of the resulting shapes.

Example 1:

Input: [[2]]
Output: 10

Example 2:

Input: [[1,2],[3,4]]
Output: 34

Example 3:

Input: [[1,0],[0,2]]
Output: 16

Example 4:

Input: [[1,1,1],[1,0,1],[1,1,1]]
Output: 32

Example 5:

Input: [[2,2,2],[2,1,2],[2,2,2]]
Output: 46

Note:

  • 1 <= N <= 50
  • 0 <= grid[i][j] <= 50

C++ 实现 1

前面还有一道类似的, 883. Projection Area of 3D Shapes*.

本题解法来自: [C++/Java/1-line Python] Minus Hidden Area

思路是: 对于 v 个堆叠起来的方块, 面积是 4 * v + 2 (四个面 + 上下两面).
如果相邻位置的都有方块, 会发生面积重叠的方块个数是 min(v1, v2), 而重叠的面积是 2 * min(v1, v2), 因此只需要用总面积减去这部分重叠面积即可.

另外这题的思路也可以用于 463. Island Perimeter* 这道题.

class Solution {
public:
    int surfaceArea(vector<vector<int>>& grid) {
        int res = 0, n = grid.size();
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j]) res += grid[i][j] * 4 + 2;
            	// 要比较左右/上下重叠的部分
                if (i) res -= min(grid[i][j], grid[i - 1][j]) * 2;
                if (j) res -= min(grid[i][j], grid[i][j - 1]) * 2;
            }
        }
        return res;
    }
};
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>简约图片轮播展示器</title> <style> /* 全局重置 */ * { margin: 0; padding: 0; box-sizing: border-box; } /* 页面基础样式 */ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f0f2f5; /* 简约的浅灰色背景 */ min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 0px; } /* 轮播主容器 */ .carousel-container { max-width: 80%; width: 100%; overflow: hidden; border-radius: 12px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08); /* 微妙的阴影 */ margin: 0 auto; } /* 轮播轨道 */ .carousel { display: flex; transition: transform 0.6s cubic-bezier(0.25, 0.1, 0.25, 1); height: 400px; } /* 轮播项 */ .carousel-item { min-width: 25%; /* 默认每屏显示4张 */ height: 100%; position: relative; overflow: hidden; transition: transform 0.3s; } /* 图片悬停效果 */ .carousel-item:hover { transform: scale(1.03); z-index: 2; } /* 图片样式 */ .carousel-item img { width: 100%; height: 100%; object-fit: cover; display: block; } /* 图片信息面板 */ .image-info { position: absolute; height: 190px; /* 统一高度 */ bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.75); color: white; padding: 15px; transform: translateY(0); transition: transform 0.3s ease; } /* 悬停时显示信息 */ .carousel-item:hover .image-info { transform: translateY(100%); } /* 信息标题 */ .image-info h3 { margin-bottom: 5px; font-size: 1.1rem; font-weight: 600; } /* 信息描述 */ .image-info p { font-size: 0.9rem; opacity: 0.9; } /* 控制按钮容器 */ .carousel-controls { display: flex; justify-content: center; gap: 15px; margin-top: 25px; } /* 简约按钮样式 */ .control-btn { background: #000; color: #fff; border: 2px solid #e0e0e0; padding: 10px 25px; border-radius: 8px; cursor: pointer; font-size: 0.95rem; font-weight: 600; transition: all 0.3s; min-width: 120px; } /* 按钮悬停效果 */ .control-btn:hover { background: #fff; border-color: #000; color: #000; } /* 按钮活动状态 */ .control-btn:active { transform: translateY(1px); } /* 指示器容器 */ .indicator { display: flex; justify-content: center; gap: 10px; margin-top: 20px; padding: 5px; } /* 指示点样式 */ .indicator-dot { width: 12px; height: 12px; border-radius: 50%; background: #fff; cursor: pointer; transition: all 0.3s; } /* 当前激活的指示点 */ .indicator-dot.active { background: #000; transform: scale(1.2); } /* 响应式设计 */ @media (max-width: 900px) { .carousel-item { min-width: 33.333%; /* 中等屏幕每屏显示3张 */ } } @media (max-width: 700px) { .carousel-item { min-width: 50%; /* 小屏幕每屏显示2张 */ } .carousel { height: 350px; } } @media (max-width: 500px) { .carousel-item { min-width: 100%; /* 超小屏幕每屏显示1张 */ } .carousel { height: 300px; } .carousel-controls { flex-wrap: wrap; } .control-btn { min-width: 100px; padding: 8px 15px; } } </style> </head> <body> <!-- 轮播主容器 --> <div class="carousel-container"> <!-- 轮播轨道 --> <div class="carousel"> <!-- 轮播项1 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Lamination-Gloss_Matte1_compressed.png" alt="Lamination (Gloss/Matte)"> <div class="image-info"> <h3>Lamination (Gloss/Matte)</h3> <p>– Applying a thin plastic film over the printed sheet to enhance scratch resistance, moisture protection and overall durability. Gloss lamination yields a shiny surface, while matte lamination gives a low-sheen, soft-touch effect.</p> </div> </div> <!-- 轮播项2 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/UV-Coating-Spot_Overall_compressed.png" alt="UV Coating (Spot/Overall)"> <div class="image-info"> <h3>UV Coating (Spot/Overall)</h3> <p>– Spreading a liquid UV-curable varnish onto either selected areas (spot UV) or the entire sheet, then instantly curing it under UV light. Creates high gloss and tactile contrast.</p> </div> </div> <!-- 轮播项3 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Hot-Foil-Stamping_compressed.png" alt="Hot Foil Stamping"> <div class="image-info"> <h3>Hot Foil Stamping</h3> <p>– Transferring metallic or pigmented foil onto specific areas of the print using heat and pressure. Delivers a premium metallic sheen (gold, silver, colored foils) for logos or decorative accents.</p> </div> </div> <!-- 轮播项4 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Embossing-_-Debossing1_compressed.png" alt="Embossing / Debossing"> <div class="image-info"> <h3>Embossing / Debossing</h3> <p>– Pressing the paper between male and female dies to create a raised (emboss) or recessed (deboss) 3D relief. Adds tactile interest and a sense of depth.</p> </div> </div> <!-- 轮播项5 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Die-Cutting_compressed.png" alt="Die-Cutting"> <div class="image-info"> <h3>Die-Cutting</h3> <p>– Using a custom-made metal die to cut the printed sheet into precise shapes or create windows/slots. Essential for producing custom box shapes, hang-tabs, or intricate cut-outs.</p> </div> </div> <!-- 轮播项6 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Creasing-Folding-Crease_compressed.png" alt="Creasing (Folding Crease)"> <div class="image-info"> <h3>Creasing (Folding Crease)</h3> <p>– Impressing a crease line on the sheet to facilitate clean, accurate folds without cracking the coating or ink. Critical for boxes, folders, and other folded structures.</p> </div> </div> <!-- 轮播项7 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Spot-UV-Emboss-Combination_compressed.png" alt="Spot UV + Emboss Combination"> <div class="image-info"> <h3>Spot UV + Emboss Combination</h3> <p>– First applying spot UV coating, then embossing the same area to create a shiny, raised element. Enhances both visual shine and tactile relief simultaneously.</p> </div> </div> <!-- 轮播项8 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Laser-Finishing-Holographic-Etch-Combination_compressed.png" alt="Laser Finishing + Holographic Etch Combination"> <div class="image-info"> <h3>Laser Finishing + Holographic Etch Combination</h3> <p>– First using a focused laser beam to engrave microscopic holographic patterns onto foil or film, then sealing the treated surface through heat or UV curing to lock in the effect. Creates vivid, color-shifting visuals that shimmer with every change in viewing angle and imparts subtle textural relief, adding a futuristic premium look and an effective anti-counterfeiting feature.</p> <p>• Pearlescent varnish for shimmering, iridescent highlights</p> <p>• Matte varnish for a soft, low-gloss finish</p> <p>• Scented varnish that releases fragrance when touched</p> </div> </div> </div> <!-- 控制按钮 --> <div class="carousel-controls"> <button class="control-btn" id="prevBtn">Previous</button> <button class="control-btn" id="nextBtn">next</button> <button class="control-btn" id="autoBtn">暂停轮播</button> </div> <!-- 指示器 --> <div class="indicator"> <div class="indicator-dot active" data-index="0"></div> <div class="indicator-dot" data-index="1"></div> <div class="indicator-dot" data-index="2"></div> <div class="indicator-dot" data-index="3"></div> </div> </div> <script> // 当文档加载完成后执行 document.addEventListener('DOMContentLoaded', function() { // 获取DOM元素 const carousel = document.querySelector('.carousel'); const items = document.querySelectorAll('.carousel-item'); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const autoBtn = document.getElementById('autoBtn'); const dots = document.querySelectorAll('.indicator-dot'); // 初始化变量 let currentIndex = 0; let itemsPerView = calculateItemsPerView(); let autoPlayInterval; let isAutoPlay = true; // 计算当前视图显示的项目数 function calculateItemsPerView() { const width = window.innerWidth; if (width <= 500) return 1; if (width <= 700) return 2; if (width <= 900) return 3; return 4; } // 更新轮播位置 function updateCarousel() { // 计算每个项目的宽度百分比 const itemWidth = 100 / itemsPerView; // 计算偏移量 const offset = -currentIndex * itemWidth; // 应用转换效果 carousel.style.transform = `translateX(${offset}%)`; // 更新指示点状态 dots.forEach((dot, index) => { dot.classList.toggle('active', index === currentIndex); }); } // 下一张 function nextSlide() { // 计算最大索引 const maxIndex = items.length - itemsPerView; // 更新当前索引(循环) currentIndex = currentIndex >= maxIndex ? 0 : currentIndex + 1; updateCarousel(); } // 上一张 function prevSlide() { // 计算最大索引 const maxIndex = items.length - itemsPerView; // 更新当前索引(循环) currentIndex = currentIndex <= 0 ? maxIndex : currentIndex - 1; updateCarousel(); } // 自动轮播 function startAutoPlay() { if (isAutoPlay) { // 设置轮播间隔 autoPlayInterval = setInterval(nextSlide, 3000); // 更新按钮文本 autoBtn.textContent = 'stop'; } } // 停止自动轮播 function stopAutoPlay() { // 清除轮播间隔 clearInterval(autoPlayInterval); // 更新按钮文本 autoBtn.textContent = 'start'; } // 切换自动轮播状态 function toggleAutoPlay() { // 反转自动播放状态 isAutoPlay = !isAutoPlay; if (isAutoPlay) { startAutoPlay(); } else { stopAutoPlay(); } } // 初始化轮播 function init() { // 计算每屏显示数量 itemsPerView = calculateItemsPerView(); // 更新轮播位置 updateCarousel(); // 开始自动播放 startAutoPlay(); } // 事件监听器 nextBtn.addEventListener('click', () => { nextSlide(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); prevBtn.addEventListener('click', () => { prevSlide(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); autoBtn.addEventListener('click', toggleAutoPlay); // 为每个指示点添加点击事件 dots.forEach(dot => { dot.addEventListener('click', () => { // 获取并设置当前索引 currentIndex = parseInt(dot.getAttribute('data-index')); updateCarousel(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); }); // 窗口大小变化时重新计算 window.addEventListener('resize', () => { // 重新计算每屏显示数量 itemsPerView = calculateItemsPerView(); // 更新轮播位置 updateCarousel(); }); // 初始化轮播 init(); }); </script> </body> </html> 这个代码为什么修改了网页的字体样式,怎么修改可以让这个代码不影响网页的字体样式
06-14
### Alpha Shapes算法在Python中的实现 Alpha Shapes 是一种用于计算几何形状的技术,它可以根据一组离散点生成具有特定拓扑结构的多边形或多面体。以下是基于 Python 的 Alpha Shapes 实现方法及其应用。 #### 使用 `scipy` 和自定义函数实现 Alpha Shapes 可以利用 `scipy.spatial.Delaunay` 来构建 Delaunay 三角剖分,并通过调整参数 α 控制形状复杂度。以下是一个完整的代码示例: ```python import numpy as np from scipy.spatial import Delaunay import matplotlib.pyplot as plt def alpha_shape(points, alpha): """ 计算给定点集的 Alpha Shape。 参数: points (list of tuples): 输入点集 [(x1, y1), (x2, y2), ...] alpha (float): Alpha 值 返回: edges (set): 边集合 """ tri = Delaunay(points) edges = set() def add_edge(i, j): """ 添加一条有序边到集合中 """ if (i, j) not in edges and (j, i) not in edges: edges.add((i, j)) # 遍历所有三角形并筛选符合条件的边 for ia, ib, ic in tri.vertices: pa = points[ia] pb = points[ib] pc = points[ic] # 计算外接圆半径 a = np.linalg.norm(pa - pb) b = np.linalg.norm(pb - pc) c = np.linalg.norm(pc - pa) s = (a + b + c) / 2.0 area = abs(a * b * c / 4.0 / np.sqrt(s * (s - a) * (s - b) * (s - c))) circum_r = a * b * c / (4.0 * area) if circum_r < 1.0 / alpha: add_edge(ia, ib) add_edge(ib, ic) add_edge(ic, ia) return edges # 测试数据 points = np.random.rand(20, 2) edges = alpha_shape(points.tolist(), alpha=0.2) # 绘图 plt.figure(figsize=(8, 6)) for edge in edges: i, j = edge p1, p2 = points[[i, j]] plt.plot([p1[0], p2[0]], [p1[1], p2[1]], 'k-') plt.scatter(points[:, 0], points[:, 1], marker='o', color='blue') plt.title("Alpha Shape Example") plt.xlabel("X-axis") plt.ylabel("Y-axis") plt.axis('equal') plt.show() ``` 上述代码实现了 Alpha Shapes 算法的核心逻辑[^1],并通过绘制图形展示了其效果。 --- #### 利用第三方库 `alphashape` 除了手动实现之外,还可以借助专门设计的库来简化开发流程。例如,`alphashape` 库提供了高效的 API 接口。 安装方式如下: ```bash pip install alphashape ``` 使用示例: ```python import alphashape import matplotlib.pyplot as plt import numpy as np # 创建随机点集 points = np.random.uniform(low=-10, high=10, size=(30, 2)) # 构建 Alpha Shape alpha = 2.0 shape = alphashape.alphashape(points, alpha) # 提取边界坐标 boundary_points = shape.boundary.coords.xy # 绘图 fig, ax = plt.subplots() ax.fill(*boundary_points, alpha=0.2, fc='orange', ec='red') ax.scatter(points[:, 0], points[:, 1]) plt.title("Alpha Shape with Alphashape Library") plt.xlabel("X-axis") plt.ylabel("Y-axis") plt.axis('equal') plt.show() ``` 此方法更加简洁明了,适合快速原型验证和实际项目部署[^4]。 --- #### PCLPy 中的应用 对于三维点云处理场景,PCL(Point Cloud Library)提供了一个强大的工具链支持 Alpha Shapes 算法。可以通过 `pclpy` 将其实现于 Python 脚本中[^3]。 安装依赖项: ```bash conda install pcl py-pcl -c conda-forge ``` 简单示例: ```python import pclpy from pclpy import pcl # 加载点云数据 cloud = pcl.PointCloud.PointXYZ.from_file("point_cloud.pcd") # 初始化 Alpha Shapes 对象 search_method = pcl.search.KdTreeFLANN.PointXYZ() as_estimator = pcl.surface.AlphaShapes(cloud, search_method) # 设置 Alpha 值 as_estimator.setAlphaValue(0.5) # 执行估计操作 indices = [] coefficients = [] as_estimator.compute(indices, coefficients) print(f"Edge Indices: {indices}") print(f"Coefficients: {coefficients}") ``` 以上代码片段演示了如何结合 PCLPy 进行三维点云边界提取。 --- ### 总结 无论是二维还是三维空间,Alpha Shapes 算法都可以灵活应用于各种领域。具体实现可根据需求选择手写核心逻辑或者调用成熟框架完成任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值