95 lines
3.1 KiB
C++
95 lines
3.1 KiB
C++
#include <vector>
|
|
|
|
class Solution {
|
|
public:
|
|
static bool stoneGameIX(const std::vector<int>& stones) {
|
|
int s[3] {
|
|
static_cast<int>(std::count_if(stones.begin(), stones.end(), [](int n){ return n % 3 == 0; })),
|
|
static_cast<int>(std::count_if(stones.begin(), stones.end(), [](int n){ return n % 3 == 1; })),
|
|
static_cast<int>(std::count_if(stones.begin(), stones.end(), [](int n){ return n % 3 == 2; }))
|
|
};
|
|
|
|
/**
|
|
* If now state is '1', next should take '1' and state changes to '2'.
|
|
* If '2', next should take '2' and state changes to 4 --%3--> '1'.
|
|
*
|
|
* If s[0] % 2 == 1, Alice will take what it originally takes.
|
|
* Otherwise, Alice will take what it not takes originally.
|
|
*
|
|
* Why? To make oneself not to fail, one must take the contrary (1 <--> 2)
|
|
* of the previous take. 2 players means that one should constantly take
|
|
* the pile which belongs to (in fact, if not, it fails immediately) it.
|
|
* And consider '3's. Taking them does not change the sum mod 3, just like
|
|
* a switch to force your opponent to take what originally "belongs to" you.
|
|
* No one wants to fail. Assume that there is not any '3's, taking the pile
|
|
* with fewer stones will definitely fail. If possible, one will try its
|
|
* best to make its opponent to take the more one.
|
|
*
|
|
* After the 1st take, the one who take the pile with fewer stones fails.
|
|
*
|
|
* When abs(s[1] - s[2]) >= 3, Alice determines what it takes by inspecting s[0].
|
|
* In this case, Alice wins.
|
|
*
|
|
* Then we must consider the possibility of taking all stones.
|
|
* Since abs(s[1] - s[2]) < 3, it is impossible to trigger rule I and there is no
|
|
* need to consider "took all but found sum mod 3 == 0". (except s[1] == s[2])
|
|
* Taking all stones will always result the winning of Bob. Discussions below:
|
|
*
|
|
* Case abs(..) == 2:
|
|
* Case s[0] % 2 == 0:
|
|
* Alice wins: take the fewer --> Bob fails by taking sum mod 3 == 0;
|
|
* Else:
|
|
* Bob wins: Taking the fewer pile --> Alice takes make sum mod 3 == 0 --> Fails
|
|
* Taking the more pile --> Alice takes the last one --> Fails
|
|
* Case abs(..) == 1:
|
|
* Case s[0] % 2 == 0:
|
|
* ditto.
|
|
* Else:
|
|
* ditto.
|
|
* Case abs(..) == 0:
|
|
* Case s[0] % 2 == 0:
|
|
* Taking any will result in Bob's failure: taking the last one but sum % 3 == 0.
|
|
* Else:
|
|
* Taking any will result in Alice's failure: ditto.
|
|
*
|
|
* Special: one pile is == 1.
|
|
* Case s[0] % 2 == 0:
|
|
* Alice take the pile with only one stone then wins.
|
|
* Else:
|
|
*
|
|
*/
|
|
if ((!s[1] && !s[2]) || (s[0] + s[1] + s[2]) == 1)
|
|
return false;
|
|
if (!s[1] || !s[2]) {
|
|
switch (s[1] ? s[1] : s[2]) {
|
|
case 0:
|
|
// unreachable
|
|
case 1:
|
|
case 2:
|
|
return false;
|
|
default:
|
|
return s[0] & 1;
|
|
}
|
|
}
|
|
if (s[1] == 1 || s[2] == 1) {
|
|
if (!(s[0] & 1))
|
|
return true;
|
|
return (s[1] == 1 ? s[2] : s[1]) > 3;
|
|
}
|
|
switch (std::abs(s[1] - s[2])) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
return !(s[0] & 1);
|
|
default:
|
|
return true;
|
|
}
|
|
// unreachable
|
|
}
|
|
};
|
|
|
|
int main() {
|
|
std::vector<int> arg(100000, 10000);
|
|
return Solution::stoneGameIX({3, 1, 1, 1});
|
|
}
|