[LeetCode] 背包问题 & 组合数学

157 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情

279. 完全平方数

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 1:

输入:n = 12
输出:3 
解释:12 = 4 + 4 + 4

示例 2:

输入:n = 13
输出:2
解释:13 = 4 + 9

提示:

  • 1 <= n <= 10^4
class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n + 1,0);
        for(int i = 1; i <= n; i++){
            dp[i] = i;
            for(int j = 1; i - j * j >= 0; j++){
                dp[i] = min(dp[i] , dp[i - j * j] + 1);
            }
        }
        return dp[n];
    }
};

1799. N 次操作后的最大分数和

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

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

  • 选择两个元素 x 和 y 。
  • 获得分数 i * gcd(x, y) 。
  • 将 x 和 y 从 nums 中删除。

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

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

示例 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
class Solution {
public:
    int gcd[15][15]; 
    int maxScore(vector<int>& nums) {
        int n = nums.size();
        //预处理gcd
        for(int i = 0; i < n; i++){
            for(int j = i + 1; j < n; j++){
                gcd[i][j] = __gcd(nums[i],nums[j]);
            }
        }
​
        vector<int> dp(1 << n,0);
        
        //记忆化搜索
        std::function<int(int,int)> dfs = [&](int state,int cnt){
            if(dp[state] != 0) return dp[state];
            for(int i = 0; i < n; i++){
                for(int j = i + 1; j < n; j++){
                    if(( (state >> i) & 1 ) == 0 or ((state >> j) & 1 ) == 0 ) continue;
                    int cur_state = state ^ (1 << i) ^ (1 << j);
                    dp[state] = max(dp[state],dfs(cur_state,cnt + 1) + cnt * gcd[i][j]);
                    
                }
            }
            return dp[state];
        };
        
        return dfs((1 << n) - 1,1);
    }
};