codeforces 695 Three Bags

题目链接:https://codeforces.com/contest/1467/problem/C

题目大意就为在三个袋子中任选两个袋子,分别从两个袋子中取出一个数a,b,使a = a - b,b被删除。一直重复进行此操作,使三个袋子中最终只剩下一个袋子里有一个值,且这个值是经过此变换得来的最大值,求这个最大值。

思路

(最开始直接看漏了要从两个袋子里面取值,然后就直接将所有输入值sort,wa到怀疑人生。。。)
我们先假设三个袋子为A,B,C。假设三个袋子中各自只有一个值,分别为a,b,c、,首先我们取b,c得到b’ = b - c,然后我们取a,b’得到a’ = a - b’,那我们进行的操作就是res = a - (b - c) = a - b + c;以此类推我们还可以得到res = b - a + c;res = a - c + b。那么我们所求的答案就应该是三个res中最大的那个,换一个角度来说max = a + b + c - 2 * MIN(a, b, c)。

那么当袋子里不止一个数字的时候呢。我们通过刚刚的例子可以看到,一个数要是直接到达终点袋子,若该数经历过奇数次变换位置就是负数(如b直接到达c,b为负数,即c - b);经历偶数次变换位置就为正数(如b先到a再到c,即c - (a - b))。那么我们只需要让尽量小且尽量少的数经历奇数次变换,即直接到目标袋子,而尽量大尽量多的数经历偶数次变换,即先到较小数的袋子,变为(min - max),再到目标袋子。

这就有两种实现方法
方法一:将一个袋子作为较小数袋,成为较大数的过渡袋。比如将A中的值的和很小,那么我们将A变为过渡袋,B、C当中的所有值(此处假设C为目标袋子)都要经过A再到目标位置那么Ai = (Ai - Bj) - Ck ,则resmax = sum(B) + sum(C) - sum(A),(对于目标袋子C来说,C中的值c→a→c,就 好像 没动)。如果sum(A)没有足够的小,那么就会引起下一个方法

方法二:若B1 + A1小于任何一个袋子中所有数的和,那么我们将B1 和 A1看作过渡位置,即将A2 – Alen(A)先经过B1; B2 – Blen(B)先经过A1,再到目标袋子,而C袋子则随意经过其中一个袋子,再到目标袋子即C袋(就相当于没变化);

在选择方法的时候,~~(小孩子才做选择,成年人的我都要,嘿嘿)~~我们只需要先将A,B,C袋子中的数字排序,再分别求和SUMA,SUMB,SUMC,再任意组合其中两个袋子的最小值计算和,然后比较这六个值的最小值得到min,然后再将所有数字加起来的时候,减去2 * min就好了(一定是二倍,其中自己想)

AC代码

#include <bits/stdc++.h>
using namespace std;

const int M = 3e5 + 10;
typedef long long ll;
int a[M], b[M], c[M];

void in(int *a, int n, ll &sum){
    for(int i = 0; i < n; i ++) {
        cin >> a[i];
        sum += a[i];
    }
    sort(a, a + n);
}
int main (){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    
    int n1, n2, n3; cin >> n1 >> n2 >> n3;
    ll s1 = 0, s2 = 0, s3 = 0;
    in(a, n1, s1);
    in(b, n2, s2);
    in(c, n3, s3);
    ll sum = s1 + s2 + s3;
    ll sub = min(s1, min(s2, s3));
    sub = min(sub, 1ll * a[0] + b[0]);
    sub = min(sub, 1ll * b[0] + c[0]);
    sub = min(sub, 1ll * a[0] + c[0]);
    cout << sum - 2 * sub << "\n";
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值