给定 3 个正整数,求最大步数将它们减少到 0

Posted

技术标签:

【中文标题】给定 3 个正整数,求最大步数将它们减少到 0【英文标题】:Given 3 positive integers, find max number of steps to reduce them to 0 【发布时间】:2020-03-26 17:54:54 【问题描述】:

我正在从 CodeForces 解决this question:

我们得到三个值,rgb,分别代表三堆中红色、绿色和蓝色糖果的数量。 Tanya 一天不能吃两颗相同颜色的糖果,也就是说,她每天只吃两颗不同颜色的糖果。找出 Tanya 可以吃糖果的最大天数。

我做了一个简单的方法如下:

int main() 
    int t, r, g, b;
    cin>>t;

    while(t--) 
        int counter=0;
        cin >> r >> g >> b;

        while(r && g) 
            r--;
            g--;
            counter++;
        

        while(g && b) 
            g--;
            b--;
            counter++;
        

        while(r && b) 
            r--;
            b--;
            counter++;
        

        cout<<counter<<"\n";
    

    return 0;

但是,它在输入 7 4 108 2 8 上中断。我的代码分别返回78,而不是109(我不确定109 如何是输入的预期答案)。 editorial 讨论对输入进行排序并检查 b &lt;= r + g 是否返回 (r+g+b)/2 如果 truer+g 否则返回。我只想说,我无法理解社论说什么。

有人可以指出为什么 我的 逻辑不正确以及我缺少什么吗?

谢谢!

【问题讨论】:

【参考方案1】:

即使您的解决方案得到纠正,它也可能无法通过 codeforces 上的所有测试,因为它的时间复杂度与输入数字的值成正比。但是有一个解决方案,无论输入数字如何,运行时间都是恒定的。

首先,对3 输入的数字进行排序。如果它们没有排序,那么在每次迭代中,我们需要找到最大和最小元素,然后递减它们。如果对数字进行了排序,那么我们会立即知道最大和最小数字在哪里,因此我们可以立即将它们递减。

现在,在排序之后,让我们考虑a,b,c: a&lt;=b&lt;=c 的可能情况:

0.如果a0(或a,ba,b,c)那么这个数字显然是min(b,c)

1.对于a, b, c: b = c, a &gt; 0,最好依次递减a,b 然后a,c,因为它会产生最大迭代次数。例如,2,3,3 -> 1,2,3 -> 0,2,2 -> 0,1,1 -> 0,0,0。如果a = c and b = c,那么它仍然是true - 2,2,2 -> 1,1,2 -> 0,1,1 -> 0,0,0

2.对于a, b, c: a != b and b != c,我们应该牢记1 最大化迭代次数的情况。如何到那?好吧,通过递减ca,只要a 变为0(那么就不需要大小写1,因为我们已经可以将剩余步骤计算为min(b, c - a))或c 变为等于b,然后是1。如果我们尝试减少任何其他数字对,那么迭代次数将减少,因为b 将无缘无故减少:)。在此之后我们可以申请案例1

3.这种方法可以在O(1)时间复杂度下实现。

...    

int main() 
    int t;
    std::cin >> t;

    for (int i = 0; i < t; i++) 
        std::vector<int32_t> array(3);
        for (int32_t& value : array) 
            std::cin >> value;
        
        std::sort(array.begin(), array.end());
        int32_t days = 0;

        int32_t diff = array[2] - array[1];
        days += (std::min(array[0], diff));
        array[0] -= days;
        array[2] -= days;

        array[2] -= array[0] / 2;
        days += (array[0] / 2);

        array[1] -= array[0] / 2;
        days += (array[0] / 2);

        days += std::min(array[1], array[2]);

        std::cout << days << std::endl;
    

    return 0;


...

【讨论】:

【参考方案2】:

因为你需要找到解决这个问题的最佳方法。

比如1,1,10,最优的方式是r&b,g&b。在你的方法中,结果只有 1。

因此我们需要对三个值进行排序,并始终使用最大的数字来得出答案。

【讨论】:

以上是关于给定 3 个正整数,求最大步数将它们减少到 0的主要内容,如果未能解决你的问题,请参考以下文章

正整数拆分问题 将一个给定的正整数n拆分成若干个在a到b之间的正整数之和,有多少种拆法

C++_求2个或3个正整数中的最大数,用带有默认参数的函数实现

定和的n个正整数 求最大积

L1-022 奇偶分家

C语言编程:输入两个正整数m和n,求它们的最大公约数。

C语言编程:输入两个正整数m和n,求它们的最大公约数。