问题 F: 最少操作次数
内存限制:128 MB时间限制:2.000 S
题目描述
黑板上写着三个整数 A,B,C。
你可以以任意顺序执行以下两个操作任意次:
选择其中两个数,并将这两个数减 1。
将三个数都减 1。
你的目标是使黑板上的所有数字都为 0。
确定目标是否可以实现。如果是,请输出最少的操作次数。
输入
一行三个空格分隔的整数 A,B,C。
0≤A,B,C≤1018
输出
如果目标不可实现,请输出 −1。
否则,请输出最少操作次数。
样例输入 复制
2 2 3
样例输出 复制
3
提示
选择 A,C 减 1。数字变成 1,2,2。
选择 B,C 减 1。数字变成 1,1,1。
对所有数减 1。数字变成 0,0,0。
官方题解逻辑也大致一样.分享一下我的思路:
我的思路是挑两个数减一和三个数都减一这两种操作里,肯定是尽量挑三个数都减一能达到最少操作次数,因为三次前者才等于两次后者。所以我们要先处理三个数,使得它们相等。我们的处理操作就是挑两个数减一。
那么问题就变成怎么挑两个数减一,能够使得三个数相等?
很显然,我们可以用二元一次方程组去做,假设随便给出101 88 90三个数:
101-n-k=90-n;
101-n-k=88-k;
n+k显然就是我们要的操作次数;但不用解出该方程,因为我们又发现,我们最后还要加上三个数都减一的次数,也就是101-n-k(==90-n==88-k),加上n+k就是101,也就是三个数中最大的那个数。这道题的目标直接转变为求三个数的最大数即可。
同样我们需要讨论无法实现的情况,这里先直接给出结论,a>b+c.
也不用复杂的证明,倒着做;设a为最大值,a=b+c可以ac和ab共减1即可得0,那么a>b+c时a减完c减完b之后还有剩余。无法再进行。
萌新一般的AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<vector>
#include<set>
using namespace std;
//三个数不是三角形不行(但是可以两边加和=最长)
//直接输出最大数
int main()
{
long long a, b, c;
cin >> a >> b >>c;
if (a > b + c || b > a + c || c > b + a)
{
cout << -1 << endl;
exit(0);
}
else
{
if (a > b && a > c)
cout << a << endl;
else if (b > a && b > c)
cout << b << endl;
else
cout << c << endl;
}
return 0;
}