LeetCode 5695. N 次操作后的最大分数和(状压dp)

题意:

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

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

选择两个元素 x 和 y 。
获得分数 i * gcd(x, y) 。
将 x 和 y 从 nums 中删除。
请你返回 n 次操作后你能获得的分数和最大为多少。

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

数据范围:
1 <= n <= 7
nums.length == 2 * n
1 <= nums[i] <= 1e6

解法:

令d[i][j]表示i次操作,当前剩余数状态为j的最大权值和.其中j是一个二进制数.
枚举j中未使用的数的下标x和y进行转移.
d[i][j]可以转移到d[i+1][j^(1<<x)^(1<<y)],转移收益为gcd(a[x],a[y]).

code:

int d[10][(1<<14)];
class Solution {
    
    
public:
    int maxScore(vector<int>& a) {
    
    
        int n=a.size();
        for(int i=0;i<=n/2;i++){
    
    
            for(int j=0;j<(1<<n);j++){
    
    
                d[i][j]=-2e9;
            }
        }
        d[0][(1<<n)-1]=0;
        for(int i=0;i<n/2;i++){
    
    
            for(int j=0;j<(1<<n);j++){
    
    
                if(d[i][j]==-2e9)continue;
                for(int x=0;x<n;x++){
    
    
                    if(j>>x&1){
    
    
                        for(int y=x+1;y<n;y++){
    
    
                            if(j>>y&1){
    
    
                                int t=__gcd(a[x],a[y]);
                                int nt=(j^(1<<x)^(1<<y));
                                d[i+1][nt]=max(d[i+1][nt],d[i][j]+(i+1)*t);
                            }
                        }
                    }
                }
            }
        }
        return d[n/2][0];
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/115056322