以下函数计算给定信息的最大尺寸图块。
如果它是用 Python 编写的这一事实让您难以理解,请在评论中告诉我,我会尝试用其他语言来完成。
import math
from __future__ import division
def max_tile_size(tile_count, rect_size):
"""
Determine the maximum sized tile possible.
Keyword arguments:
tile_count -- Number of tiles to fit
rect_size -- 2-tuple of rectangle size as (width, height)
"""
# If the rectangle is taller than it is wide, reverse its dimensions
if rect_size[0] < rect_size[1]:
rect_size = rect_size[1], rect_size[0]
# Rectangle aspect ratio
rect_ar = rect_size[0] / rect_size[1]
# tiles_max_height is the square root of tile_count, rounded up
tiles_max_height = math.ceil(math.sqrt(tile_count))
best_tile_size = 0
# i in the range [1, tile_max_height], inclusive
for i in range(1, tiles_max_height + 1):
# tiles_used is the arrangement of tiles (width, height)
tiles_used = math.ceil(tile_count / i), i
# tiles_ar is the aspect ratio of this arrangement
tiles_ar = tiles_used[0] / tiles_used[1]
# Calculate the size of each tile
# Tile pattern is flatter than rectangle
if tile_ar > rect_ar:
tile_size = rect_size[0] / tiles_used[0]
# Tile pattern is skinnier than rectangle
else:
tile_size = rect_size[1] / tiles_used[1]
# Check if this is the best answer so far
if tile_size > best_tile_size:
best_tile_size = tile_size
return best_tile_size
print max_tile_size(4, (100, 100))
该算法可以大致描述如下
- 如果矩形比它的宽度高,翻转它,使它比它的高更宽。
- 计算s,即瓷砖数量的平方根,四舍五入。
tiles_max_height
(在代码中命名。)
- 循环i从 1 到s(含):
- 构建一个正方形网格,其数量为瓦片数 / i方格宽和i方格高。(将所有内容四舍五入。这会“填充”缺失的图块,例如当您的图块总数为 3 时使用 2 个图块乘 2 个图块。)
- 使这个网格尽可能大。(使用纵横比计算。)确定一个图块的大小。
- 使用该尺寸,确定瓷砖覆盖的总面积。
- 检查这是否是迄今为止最好的总面积;如果是,存储正方形大小
- 返回那个正方形大小
这可能是这里列出的更快的算法之一,因为它计算n 个图块的 O(sqrt( n )) 中的最佳平方大小。
更新
进一步考虑,这个问题有一个基于上述解决方案的更简单的解决方案。假设你有 30 个瓷砖。您可能的瓷砖排列很容易计算:
- 30 x 1(纵横比 30.0000)
- 15 x 2(纵横比 7.5000)
- 10 x 3(纵横比 3.3333)
- 8 x 4(纵横比 2.0000)
- 6 x 5(纵横比 1.2000)
- 6 x 6(纵横比 1.0000)
假设你的矩形是 100 x 60。你的矩形的纵横比是 1.6667。这介于 1.2 和 2 之间。现在,您只需计算 8 x 4 和 6 x 5 排列的图块大小。
第一步在技术上仍然需要 O(sqrt( n )),所以这个更新的方法并不比第一次尝试快。
来自评论线程的一些更新
/*
Changes made:
tiles_used -> tiles_used_columns, tiles_used_rows
(it was originally a 2-tuple in the form (colums, rows))
*/
/* Determine the maximum sized tile possible. */
private function wesleyGetTileSize() : Number {
var tile_count : Number = slideCount.value;
var b : Number = heightOfBox.value;
var a : Number = widthOfBox.value;
var ratio : Number;
// // If the rectangle is taller than it is wide, reverse its dimensions
if (a < b) {
b = widthOfBox.value;
a = heightOfBox.value;
}
// Rectangle aspect ratio
ratio = a / b;
// tiles_max_height is the square root of tile_count, rounded up
var tiles_max_height : Number = Math.ceil(Math.sqrt(tile_count))
var tiles_used_columns : Number;
var tiles_used_rows : Number;
var tiles_ar : Number;
var tile_size : Number;
var best_tile_size : Number = 0;
// i in the range [1, tile_max_height], inclusive
for(var i: Number = 1; i <= tiles_max_height + 1; i++) {
// tiles_used is the arrangement of tiles (width, height)
tiles_used_columns = Math.ceil(tile_count / i);
tiles_used_rows = i;
// tiles_ar is the aspect ratio of this arrangement
tiles_ar = tiles_used_columns / tiles_used_rows;
// Calculate the size of each tile
// Tile pattern is flatter than rectangle
if (tiles_ar > ratio){
tile_size = a / tiles_used[0] ;
}
// Tile pattern is skinnier than rectangle
else {
tile_size = b / tiles_used[1];
}
// Check if this is the best answer so far
if (tile_size > best_tile_size){
best_tile_size = tile_size;
}
}
returnedSize.text = String(best_tile_size);
return best_tile_size;
}