前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode 1799. N 次操作后的最大分数和(回溯 / 状态压缩DP)

LeetCode 1799. N 次操作后的最大分数和(回溯 / 状态压缩DP)

作者头像
Michael阿明
发布2021-09-06 10:19:53
4850
发布2021-09-06 10:19:53
举报
文章被收录于专栏:Michael阿明学习之路

文章目录

1. 题目

给你 nums ,它是一个大小为 2 * n 的正整数数组。 你必须对这个数组执行 n 次操作。

在第 i 次操作时(操作编号从 1 开始),你需要:

  • 选择两个元素 xy
  • 获得分数 i * gcd(x, y)
  • xynums 中删除。

请你返回 n 次操作后你能获得的分数和最大为多少。

函数 gcd(x, y) 是 x 和 y 的最大公约数。

代码语言:javascript
复制
示例 1:
输入:nums = [1,2]
输出:1
解释:最优操作是:
(1 * gcd(1, 2)) = 1

示例 2:
输入:nums = [3,4,6,8]
输出:11
解释:最优操作是:
(1 * gcd(3, 6)) + (2 * gcd(4, 8)) = 3 + 8 = 11

示例 3:
输入:nums = [1,2,3,4,5,6]
输出:14
解释:最优操作是:
(1 * gcd(1, 5)) + (2 * gcd(2, 4)) + (3 * gcd(3, 6)) = 1 + 4 + 9 = 14
 
提示:
1 <= n <= 7
nums.length == 2 * n
1 <= nums[i] <= 10^6

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/maximize-score-after-n-operations 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

2.1 错误解

  • 贪心取最大的得分组合,有可能不是最佳方案,[481851,31842,817070,452937,627635,712245]最后的例子过不了
代码语言:javascript
复制
class Solution {
public:
    int maxScore(vector<int>& nums) {
        vector<vector<int>> g(nums.size(),vector<int>(nums.size()));
        priority_queue<tuple<int, int, int, int>> q;
        for(int i = 0; i < nums.size(); ++i)
        {
            for(int j = i+1; j < nums.size(); ++j)
            {
                g[i][j] = __gcd(nums[i], nums[j]);
                for(int k = 1; k <= nums.size()/2; ++k)
                {
                    q.push(tuple(k*g[i][j], i, j, k));
                }
            }
        }
        vector<bool> vis(nums.size(), false), visk(nums.size()/2+1, false);
        int count = nums.size()/2;
        int ans = 0;
        while(count)
        {
            auto [p, i, j, k] = q.top();
            q.pop();
            if(vis[i] || vis[j] || visk[k])
                continue;
            vis[i] = true;
            vis[j] = true;
            visk[k] = true;
            count--;
            ans += p;
        }
        return ans;
    }
};

2.2 回溯超时解

  • 通过 46/66
代码语言:javascript
复制
class Solution {
    int maxS = 0;
public:
    int maxScore(vector<int>& nums) {
        vector<bool> vis(nums.size(), false);
        sort(nums.begin(),nums.end());
        vector<vector<int>> g(nums.size(),vector<int>(nums.size()));
        for(int i = 0; i < nums.size(); ++i)
        {
            for(int j = i+1; j < nums.size(); ++j)
            {
                g[i][j] = __gcd(nums[i], nums[j]);
            }
        }
        dfs(nums, 0, 0, vis, g);
        return maxS;
    }
    void dfs(vector<int>& nums, int ct, int p, vector<bool>& vis, vector<vector<int>> &g)
    {
        if(ct == nums.size()/2)
        {
            if(p > maxS)
                maxS = p;
            return;
        }
        int i = 0, j;
        for( ; i < nums.size(); ++i)
        {
            if(!vis[i])
            {
                vis[i] = true;
                for(j=i+1 ; j < nums.size(); ++j)
                {
                    if(!vis[j])
                    {
                        vis[j] = true;
                        dfs(nums, ct+1, p+(ct+1)*g[i][j], vis, g);
                        vis[j] = false;
                    }
                }
                vis[i] = false;
            }
        }        
    }
};

2.3 回溯通过

代码语言:javascript
复制
class Solution {
    int maxS = 0;
public:
    int maxScore(vector<int>& nums) {
        vector<bool> vis(nums.size(), false);
        vector<vector<int>> g(nums.size(),vector<int>(nums.size()));
        for(int i = 0; i < nums.size(); ++i)
        {
            for(int j = 0; j < nums.size(); ++j)
            {
                g[i][j] = __gcd(nums[i], nums[j]);
            }
        }
        vector<int> path;
        dfs(nums, 0, vis, g, path);
        return maxS;
    }
    void dfs(vector<int>& nums, int idx, vector<bool>& vis, vector<vector<int>> &g, vector<int>& path)
    {
        if(idx == nums.size()/2)
        {
            int s = 0;
            vector<int> v = path;
            sort(v.begin(), v.end());
            for(int i = 0; i < v.size(); i++)
            {
                s += (i+1)*v[i];
            }
            maxS = max(maxS, s);
            return;
        }
        int i = 0, j = 0;
        for( ; i < nums.size(); ++i)
        {
            if(vis[i]) continue;
            break;
        }
        vis[i] = true;
        for( ; j < nums.size(); ++j)
        {
            if(!vis[j])
            {
                vis[j] = true;
                path.push_back(g[i][j]);
                dfs(nums, idx+1, vis, g, path);
                path.pop_back();
                vis[j] = false;
            }
        }
        vis[i] = false;
    }
};

884 ms 82.7 MB C++

2.4 状态压缩DP

代码语言:javascript
复制
class Solution {
public:
    int maxScore(vector<int>& nums) {
        int n = nums.size(), cti, ctj;
        vector<int> dp(1<<n);
        for(int i = 0; i < n; ++i)
        {
            for(int j = i+1; j < n; ++j)
                dp[(1<<i)|(1<<j)] = __gcd(nums[i], nums[j]);

        }
        for(int i = 0; i < (1<<n); ++i)
        {
            cti = count(i);
            if(cti%2 == 1) continue;
            for(int j = i; j>0; j=(j-1)&i)
            {
                ctj = count(j);
                if(cti-ctj == 2)// 相差一对数,从 j 转移到 i
                {
                    dp[i] = max(dp[i], dp[j]+cti/2*dp[i^j]);
                }
            }
        }
        return dp[(1<<n)-1];
    }
    int count(int x)
    {   // 计算二进制1个数
        int s = 0;
        while(x)
        {
            s++;
            x = x&(x-1);
        }
        return s;
    }
};

140 ms 8.2 MB C++


我的CSDN博客地址 https://michael.blog.csdn.net/

长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/03/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1. 题目
  • 2. 解题
    • 2.1 错误解
      • 2.2 回溯超时解
        • 2.3 回溯通过
          • 2.4 状态压缩DP
          相关产品与服务
          文件存储
          文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档