翻转卡片以获得最大金额

Flip cards to get maximum sum

本文关键字:金额 翻转      更新时间:2023-10-16

给定N张牌,如果第一张牌正面有数字x,那么背面就会有数字-x,并且一个操作只能执行一次,即按连续顺序翻转任意数量的牌只能执行一次。

现在我们需要翻转牌的方式是使牌的正面数量的总和是最大的

示例:如果N=5, cards[]为{-2,3,-1,-4,-2},那么这里的答案是8,因为我们可以翻转最后3张牌得到配置{-2,3,1,4,2},和为8。

My Approach:

对每一个以位置为起始位置的可能路径进行遍历并求最大值。但对于这个问题,他们有更好的解决方案吗?

我的代码:我还没有找到问题

#include<bits/stdc++.h>
using namespace std;
int solve(std::vector<int> const & numbers)
{
    int min_so_far  = numbers[0], min_ending_here = numbers[0];
    size_t begin = 0;
    size_t begin_temp = 0;
    size_t end = 0;
    for(size_t i = 1; i < numbers.size(); i++)
    {
            if(min_ending_here > 0)
            {
                    min_ending_here = numbers[i];
                    begin_temp = i;
            }
            else
            {
                    min_ending_here += numbers[i];
            }
            if(min_ending_here <= min_so_far )
            {
                    min_so_far  = min_ending_here;
                    begin = begin_temp;
                    end = i;
            }
    }
    int sum=0;
    for(int i=0;i<begin;i++){
        sum+=numbers[i];
    }
    for(int i=begin;i<=end;i++){
        sum-=numbers[i];
    }
    for(int i=end+1;i<numbers.size();i++){
        sum+=numbers[i];
    }
    return sum;
}
int main(){
int n;
cin>>n;
vector<int> arr;
for(int i=0;i<n;i++){
    int x;
    cin>>x;
    arr.push_back(x);
}
  cout<<solve(arr)<<"n";
}

你唯一需要做的就是找到你可以用连续数字组成的最小和,然后翻转它们。在你的例子中,最后三个数字加起来是-7,并且没有其他连续数字的和比它们更低,所以翻转它们就可以了。如果最小和是非负的,那么你不需要翻转它们。

现在,我上面描述的是一个众所周知的算法,它被称为Kadane算法,它可以在O(n)内求解,注意维基百科的链接显示了如何对最大值进行求解,但你可以很容易地修改它来找到最小值

我在这里使用了Kadane的算法方法,最小子数组和函数返回O(n)中的最小和,因为我们已经有了数组中所有元素的和,所以我们将添加(-2)min_sum的时间,因为它被扣除了一次。

#include<bits/stdc++.h>
using namespace std;
int minsubarraysum(int a[], int n) {
    int min_sum = INT_MAX;
    int curr_sum = 0;
    for (int i = 0 ; i < n; i++) {
        curr_sum = curr_sum + a[i];
        if (curr_sum < min_sum)
            min_sum = curr_sum;
        if (curr_sum > 0)
            curr_sum  = 0;
    }
    return min_sum;
}
int main() {
    int n;
    cin >> n;
    int a[n];
    int sum = 0;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        sum += a[i];
    }
    int min_sum = minsubarraysum(a, n);
    int ans = sum + (min_sum * (-2));
    cout << ans;
}