1753. 移除石子的最大得分

100 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第25天,点击查看活动详情

✨欢迎关注🖱点赞🎀收藏⭐留言✒

🔮本文由京与旧铺原创,csdn首发!

😘系列专栏:java学习

💻首发时间:🎞2022年12月10日🎠

🀄如果觉得博主的文章还不错的话,请三连支持一下博主哦

🎧作者是一个新人,在很多方面还做的不好,欢迎大佬指正,一起学习哦,冲冲冲

⭐️1753. 移除石子的最大得分⭐️

🔐题目详情

题目链接: 1753. 移除石子的最大得分

难度中等

你正在玩一个单人游戏,面前放置着大小分别为 abc三堆 石子。

每回合你都要从两个 不同的非空堆 中取出一颗石子,并在得分上加 1 分。当存在 两个或更多 的空堆时,游戏停止。

给你三个整数 abc ,返回可以得到的 最大分数

示例 1:

输入:a = 2, b = 4, c = 6
输出:6
解释:石子起始状态是 (2, 4, 6) ,最优的一组操作是:
- 从第一和第三堆取,石子状态现在是 (1, 4, 5)
- 从第一和第三堆取,石子状态现在是 (0, 4, 4)
- 从第二和第三堆取,石子状态现在是 (0, 3, 3)
- 从第二和第三堆取,石子状态现在是 (0, 2, 2)
- 从第二和第三堆取,石子状态现在是 (0, 1, 1)
- 从第二和第三堆取,石子状态现在是 (0, 0, 0)
总分:6 分 。

示例 2:

输入:a = 4, b = 4, c = 6
输出:7
解释:石子起始状态是 (4, 4, 6) ,最优的一组操作是:
- 从第一和第二堆取,石子状态现在是 (3, 3, 6)
- 从第一和第三堆取,石子状态现在是 (2, 3, 5)
- 从第一和第三堆取,石子状态现在是 (1, 3, 4)
- 从第一和第三堆取,石子状态现在是 (0, 3, 3)
- 从第二和第三堆取,石子状态现在是 (0, 2, 2)
- 从第二和第三堆取,石子状态现在是 (0, 1, 1)
- 从第二和第三堆取,石子状态现在是 (0, 0, 0)
总分:7 分 。

示例 3:

输入:a = 1, b = 8, c = 8
输出:8
解释:最优的一组操作是连续从第二和第三堆取 8 回合,直到将它们取空。
注意,由于第二和第三堆已经空了,游戏结束,不能继续从第一堆中取石子。

提示:

  • 1 <= a, b, c <= 105

💡解题思路

解题思路:

方法1,贪心,先将a,b,c,放入数组中,排序,每次取前两个大数减1,计分,再排序,直到前两个数都为0为止。

方法2,贪心+排序

不妨假定a<=b<=c,有以下两种情况:

  • a+b<=ca+b<=c,先将ca减少a次,再将cb减少b次,最终得分为a+ba+b
  • a+b>ca + b > c,那么c每次与ab中较大的数进行匹配。设与a匹配cnt1次,与b匹配cnt2次。最后变成(a - cnt1, b - cnt2, 0),由于每次c都与最大的数进行匹配,那么最后剩下的两个数必然相等或者相差1。如(9, 10, 12),最终变为(3, 4, 0), cnt1=6,cnt2=6cnt1=6,cnt2=6分数为cnt1+cnt2+(9cnt1+10cnt2)/2=(6+6)+(3+4)/2=15cnt1+cnt2+(9-cnt1+10-cnt2) / 2 = (6 + 6) + (3 + 4) / 2 = 15,最终公式为cnt1+cnt2+(acnt1+bcnt2)/2cnt1+cnt2+(a-cnt1+b-cnt2)/2,又cnt1+cnt2=ccnt1 + cnt2 = c,代入得(a+b+c)/2(a+b+c)/2

🔑源代码

方法1: java版本代码:

class Solution {
    public int maximumScore(int a, int b, int c) {
        //贪心,每次减少最大的俩个
        int[] arr = new int[]{a, b, c};
        int ans = 0;
        Arrays.sort(arr);
        while (arr[0] > 0 || arr[1] > 0) {
            arr[2]--;
            arr[1]--;
            ans++;
            Arrays.sort(arr);
        }
        return ans;
    }
}

c++版本代码:

class Solution {
public:
    int maximumScore(int a, int b, int c) {
        vector<int> arr = {a, b, c};
        sort(arr.begin(), arr.end());
​
        int ans = 0;
        while (arr[0] > 0 || arr[1] > 0) 
        {
            arr[2]--;
            arr[1]--;
            ans++;
            sort(arr.begin(), arr.end());
        }
​
        return ans;
    }
};

c 版本代码:

//升序
int compare(const void* a, const void* b)
{
    return (*(int*)a - *(int*)b);
}
​
int maximumScore(int a, int b, int c){
    int arr[] = {a, b, c};
    int ans = 0;
    qsort(arr, sizeof(arr) / sizeof(int), sizeof(int), compare);
    while (arr[0] > 0 || arr[1] > 0) 
    {
        arr[1]--;
        arr[2]--;
        ans++;
        qsort(arr, sizeof(arr) / sizeof(int), sizeof(int), compare);
    }
    return ans;
}

方法2: java版本代码:

class Solution {
    public int maximumScore(int a, int b, int c) {
        //贪心+数学
        int[] arr = new int[]{a, b, c};
        int ans = 0;
        Arrays.sort(arr);
        if (arr[0] + arr[1] <= arr[2]) ans = arr[0] + arr[1];
        else ans = (arr[0] + arr[1] + arr[2]) / 2;
        return ans;
    }
}

c++版本代码:

class Solution {
public:
    int maximumScore(int a, int b, int c) {
        vector<int> arr = {a, b, c};
        sort(arr.begin(), arr.end());
​
        int ans = 0;
        if (arr[0] + arr[1] <= arr[2]) ans = arr[0] + arr[1];
        else ans = (arr[0] + arr[1] + arr[2]) / 2;
​
        return ans;
    }
};

c 版本代码:

//升序
int compare(const void* a, const void* b)
{
    return (*(int*)a - *(int*)b);
}
​
int maximumScore(int a, int b, int c){
    int arr[] = {a, b, c};
    int ans = 0;
    qsort(arr, sizeof(arr) / sizeof(int), sizeof(int), compare);
    if (arr[0] + arr[1] <= arr[2]) ans = arr[0] + arr[1];
    else ans = (arr[0] + arr[1] + arr[2]) / 2;
    return ans;
}

🌱总结

本题为贪心思维运用题,数学推导题。