Мне потребовалось три попытки, чтобы понять это правильно. Ошибка в этой задаче как в задаче динамического программирования c заключалась в нисходящей спирали
. Хитрость заключается в том, чтобы признать, что ее можно решить за все время oop, где вы постоянно сортируете a,b,c
от наименьшего к наибольшему. Затем оцените, к какой схеме подходят цифры. Шаблоны для поиска включают:
- 1 или менее положительных значений в наборе:
a=0, b=0, c=5
- 2 положительных значения и ноль в наборе:
a=0, b=3, c=10
- 3 положительных значения, все разные:
a=5, b=11, c=88
- 3 положительных значения, все одинаковые:
a=10, b=10, c=10
- 3 положительных значения, наименьшие два равны:
a=5, b=5, c=22
- 3 положительных значения, самые большие два равны:
a=3, b=5, c=5
После того, как вы выясните, какой шаблон a,b,c
попадает в приведенный выше список, есть специфика c express сокращения, которые могут быть сделаны. Многие из которых позволят вам вырваться из l oop без необходимости дальнейшего уменьшения набора. И я думаю, что следующий код работает так, что он повторяется только через l oop не более 2 (или 3) раз. Следовательно, это O (1) решение .
#include <iostream>
#include <algorithm>
using namespace std;
long long maxDeductions(long long a, long long b, long long c)
{
long long total = 0; // this is the running count of "deduction" steps made so far
while (true)
{
long long deduction = 0; // scratch variable for math
// sort a,b,c into ascending order
long long sorttable[3] = { a,b,c };
sort(sorttable, sorttable + 3);
a = sorttable[0]; // smallest
b = sorttable[1]; // middle
c = sorttable[2]; // largest
// count the number of positive values among a,b,c
int positives = 0;
positives += (a > 0);
positives += (b > 0);
positives += (c > 0);
if (positives <= 1)
{
// Nothing left to do, we can break out of the loop
break;
}
else if (positives == 2)
{
// When there are only two positives left
// The number of deductions that can be express computed.
// as the smaller of the remaining positive values, that is: b
//
// ASSERT: (b <= c) && (b > 0) && (c > 0)
deduction = b;
total += deduction;
break;
}
else // three positives
{
if ((a != b) && (b != c)) // 3 positives, all different
{
// reduce the two larger values, b and c, by the delta between b and a
// this "b-a" amount is the number of deductions computed to get the set a,b,c to have
// at least 2 identical numbers for the next set
deduction = b - a;
b = a;
c -= deduction;
total += deduction;
}
else if ((a == b) && (b == c)) // 3 positives, all the same
{
// when you have 3 identical values: N,N,N
// It takes three steps to get to N-2,N-2,N-2
// With a subtle tweak for odd vs even values of N, simple math can be used to
// deduce the remaining number of deductions
if (a % 2) // odd
{
deduction = ((a - 1) / 2) * 3 + 1;
}
else // even
{
deduction = (a / 2) * 3;
}
total += deduction;
break;
}
else if (c == b) // 3 positives, largest two are the same, equivalent to all different
{
deduction = b - a;
b = a;
c -= deduction;
total += deduction;
}
else if (a == b) // 3 positives, smallest two are the same
{
// this is the tricker one, but you can quickly see the pattern:
// NNZ reduces in N*2 steps. Example for N=5
// 559 -> 548 -> 448 -> 437 -> 337 -> 326 -> 226 -> 215 -> 115 -> 104 -> 003
// You can see every two reductions steps gets N,N,Z reduced to N-1,N-1,Z-1
// Hence, exactly N*2 steps remaining
total += (a * 2);
break;
}
}
}
return total;
};