【问题标题】:How can I minimize two integers so that their product is less than a certain value?如何最小化两个整数,使它们的乘积小于某个值?
【发布时间】:2020-03-08 20:07:13
【问题描述】:

给定两个整数,我怎样才能使它们最小化,以使它们的乘积小于其他值,同时保持它们的相对比率?

这是形式问题。实际问题是这样的:我的宽度/高度像素分辨率包含随机值(任一维度从 1 到 8192)。我想调整成对的值,使它们的乘积不超过某个像素总数(例如:1000000),并且我需要确保调整后的分辨率的纵横比保持不变(例如:1.7777)。

天真的方法是运行一个循环,每次我从宽度中减去 1,调整高度以匹配纵横比,直到它们的乘积低于阈值。例如:

int wid = 1920;
int hei = 1080;
float aspect = wid / (float)hei;
int maxPixels = 1000000;
while (wid * hei > maxPixels)
{
    wid -= 1;
    hei = wid / aspect;
}

当然,对于这个问题,肯定有更分析的方法吗?

【问题讨论】:

  • 这似乎更像是一个数学问题。
  • 根据这需要的性能,天真的方法可能很接近 - 但请尝试“归位”,例如,将两个值除以 2 并查看您是否超出。有点像二分查找。围绕目标上下摆动。当你回家时减少步数乘数。我认为你的意思是“最大化”;)
  • 也不确定您的意思是“正方形”吗?你的意思是……把它们相乘,对吧?
  • 理解和公平。很高兴知道您的期望/要求是什么。会看这个。

标签: pixel resolution square


【解决方案1】:

mascoj came up with the answer,但这里是代码形式的解释:

#include <utility>
#include <numeric>
#include <cmath>
#include <iostream>

// Mathsy stuff

std::pair<uint64_t, uint64_t> ReduceRatio(const uint64_t W, const uint64_t H)
{
    const double D = std::gcd(W, H);
    return {W/D, H/D};
}

std::pair<uint64_t, uint64_t> Maximise(const uint64_t C, const uint64_t W, const uint64_t H)
{
    const auto [x, y] = ReduceRatio(W, H);
    const uint64_t F = std::floor(std::sqrt(C/double(x*y)));

    const uint64_t A = x*F;
    const uint64_t B = y*F;

    return {A, B};
}


// Test harness

void Test(const uint64_t MaxProduct, const uint64_t W, const uint64_t H)
{
    const auto [NewW, NewH] = Maximise(MaxProduct, W, H);

    std::cout << W << "\u00D7" << H << " (" << (W*H) << " pixels)";

    if (NewW > W)
        std::cout << '\n';
    else
        std::cout << " => " << NewW << "\u00D7" << NewH << " (" << (NewW * NewH) << " pixels)\n";
}

int main()
{
    Test(100000, 1024, 768);
    Test(100000, 1920, 1080);
    Test(500000, 1920, 1080);
    Test(1000000, 1920, 1080);
    Test(2000000, 1920, 1080);
    Test(4000000, 1920, 1080);
}

// g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
// 1024×768 (786432 pixels) => 364×273 (99372 pixels)
// 1920×1080 (2073600 pixels) => 416×234 (97344 pixels)
// 1920×1080 (2073600 pixels) => 928×522 (484416 pixels)
// 1920×1080 (2073600 pixels) => 1328×747 (992016 pixels)
// 1920×1080 (2073600 pixels) => 1872×1053 (1971216 pixels)
// 1920×1080 (2073600 pixels)

【讨论】:

    【解决方案2】:

    编辑:误读原始问题。

    表达您的问题的另一种方式是使用WH 什么是最大的ab,这样a/b = W/Ha*b &lt; C 其中C 是您的限制。

    为此,请找到D = gcd(W,H)WH 的最大公约数。最大公分母通常使用欧几里得算法找到。

    设置x = W/Dy = H/D,这是相同比例的最小解。

    要在C 下产生最大值,从F*x*F*y &lt;= C 的不等式开始,其中F 将是xy 的比例因子

    代数:

    F^2 &lt;= C/(x*y)

    F &lt;= sqrt(C/(x*y))

    由于我们希望 F 是一个整数并且严格小于上述值,

    F = floor(sqrt(C/(x*y)))

    这将为您提供一个新的解决方案 A = x*FB = y*F 其中A*B &lt; CA/B = W/H

    【讨论】:

    • 你确定它不是 最大 ab 这样a/b = W/Ha*b &lt;= C
    • 是的,但他也描述了这个问题(以及幼稚的方法),听起来他不想每次都得到一个 1 像素 x 1.7777 像素的图像?这似乎是“在保持纵横比的同时将图像降低到 X 分辨率”活动
    • 很好,快到了。刚刚写了b &lt;= sqrt(C/W*H):D
    • 谢谢。不确定它是否涵盖所有情况,因为我在这里并没有真正做到严格,即说明为什么 F 需要是整数。但应该是对的,希望
    • 顺便说一句,这也可以增加输入,这可能是也可能不是我们想要的。但是更高的结果很容易被丢弃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    相关资源
    最近更新 更多