把一堆自然数平均分成M组,每组自然数之和为K,如何分组才能让各组的K值最接近?

现在要为一个网站设计一个图片排版。假设图片分成三列显示,每列垂直排列10张图片,要求这三列的图片高度之和最后相等。由于图片是用户上传,所以图片尺寸无法控制,且要保持原宽高比,不能对图片进行剪切。


这个算法要求大概是这样的:


1. 把一组自然数分成 M 组,每组 N 个 ;
2. 每组自然数相加之和为 K ;
问题: 怎样分配,才能使得 K1,K2,K3....KM 之间的差值较小?
实际应用 M 在 4 到 8 之间,N 在 10 到 20 之间。现在求一个比较优化的算法,最后K1 K2 K3...KM之间的差值越小越好。


补充下问题:
1.考虑排版的美感,所有上传的图片都进行缩放,使之宽度相等。且图片的宽高比相差很大,换句话说,宽度相等后,图片之间的高度差值很大。
2.每列存放的图片数量基本相当,视觉上给人感觉是均匀分布的,比较和谐。不能为了高度相同,第一列出现10张小图片,第二列只放三张大图片。


*** 找到一个类似网站,该网站对每张图片高度进行小范围剪切(其实是在浏览器中隐藏部分高度),最后每组高度之和都一样。但不知道他们根据什么规则分组,我上传了几张新图片测试,每次有新图片之后,分组情况都不一样。


比较简单近似算法:


这些自然数按从大到小排序,然后依次分配到 M 组中,每次往当前和最小的组最后添加。


然后,如评论所说需要定义目标函数,也就是量化的评价某一个放法(configuration)的好坏程度,比如越好这个值就越大。然后就可以一定程度的优化上面的算法:


还是从大到小排序,一次往上放
定义一个概率函数,使得某个组当前的和越小其被选中的概率越大。根据这个概率密度函数,随机选一个组添加。
添加完所有的数


上面的添加完之后可以得到一个 configuration,计算一下目标函数的值。重复几次,因为有随机数,所以每次的结果不尽相同,根据工程需要确定重复次数。最后采用找到的里面目标函数最大的一组值。可以用最开始的贪心算法的结果也作为最初的候选。


有点像二维背包。但是鉴于只要保持原宽高比即可,也就是说可以在保持原宽高比的前提下对图片进行放大或缩小(即伸缩)。


一个很简单的近似算法(复杂度为O(M*N))是:按照图片的宽高比将所有图片(即M*N)分成M组(注意,这里每组的图片数目可不一定是相同的),由于每组的宽高比很相近,故每组图片可以看成是一张图片(即宽不变,高是所有图片高之和,如果想在图片上下间加适量空白,则高是所有图片高之和再加上T*L的空白,T是该组图片数量减去一或者加上一[该加该减取决于要不要考虑最上和最下的空白],L是空白距离)然后该问题就转化为将M张图片并排放在一起使得高度最接近,如果没有总宽度限制,则可设定一个高度H然后将每组图片的整体高度伸缩到该高度即可;如果有总宽度限制,则把最后屏幕的宽高比设为M组图片的平均宽高比,这样即可得到总高度,按照这个总高度将M组图片伸缩即可。当然,这个算法的前提是图片的宽高比是均匀分布的,如果某组的图片数目过多或过少可以考虑拆分成两组或者合并成一组,但要保证最后是M组。


当然,还有效果更好的算法,这个还要根据需求(时间和空间复杂度,对最后排列质量的要求等)来考虑。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值