add: 220120-CN [STAY AWAY FROM GAME THEORY]

This commit is contained in:
Lam Haoyin 2022-01-20 19:16:16 +08:00
parent 569f7138a0
commit bece329ece
No known key found for this signature in database
GPG Key ID: 8C089CB1A2B7544F
2 changed files with 95 additions and 1 deletions

94
2201/220120-CN.cpp Normal file
View File

@ -0,0 +1,94 @@
#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});
}

View File

@ -3,4 +3,4 @@ PROJECT(2201)
SET(CMAKE_CXX_STANDARD 23) SET(CMAKE_CXX_STANDARD 23)
ADD_EXECUTABLE(2201 220120.cpp) ADD_EXECUTABLE(2201 220120-CN.cpp)