Subtask:
There are $2^N$ possible boards. For each board, we can iterate over all $K$ mooves, check the total number of points scored, and possibly update the best score seen so far.
The time complexity is $O(K2^N)$. Using bitmasks can help shorten the implementation.
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, k;
cin >> n >> k;
vector<array<int, 3>> A(k);
for (auto &[x, y, z] : A) {
cin >> x >> y >> z;
x--; y--; z--;
}
int bestVal = 0;
int bestCount = 0;
for (int msk = 0; msk < (1 << n); msk++) {
int val = 0;
for (auto [x, y, z] : A)
val += ((bool)((1 << x) & msk)) && !((bool)((1 << y) & msk)) && !((bool)((1 << z) & msk));
if (val > bestVal) {
bestVal = val;
bestCount = 1;
}
else if (val == bestVal)
bestCount++;
}
cout << bestVal << " " << bestCount << "\n";
}
Full Solution 1:
Observe that there are at most $N^3/2$ possible distinct mooves ($N$ choices for each of $x$, $y$, $z$, and we can assume $y<z$ without loss of generality). So instead of maintaining a list of all $K$ mooves we can instead store for each distinct moove how many times it appears in the input in an $N\times N\times N$ array. Then for each board, we can iterate over all distinct mooves that contribute to its score and sum their counts.
The time complexity is $O(N^32^N)$ with a good constant factor. Implementations with poor constant factors should still receive significant partial credit.
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, k;
cin >> n >> k;
vector<vector<vector<int>>> isAt(n, vector<vector<int>>(n, vector<int>(n, 0)));
for (int i = 0; i < k; i++) {
int x, y, z;
cin >> x >> y >> z;
x--; y--; z--;
isAt[x][min(y, z)][max(y, z)]++;
}
vector<int> score((1 << n), 0);
for (int msk = 1; msk < (1 << n); msk++) {
vector<int> mpos, opos;
for (int i = 0; i < n; i++) {
if ((1 << i) & msk)
mpos.push_back(i);
else
opos.push_back(i);
}
for (int m : mpos)
for (int i = 0; i < opos.size(); i++)
for (int j = i + 1; j < opos.size(); j++)
score[msk] += isAt[m][opos[i]][opos[j]];
}
int bestVal = *max_element(score.begin(), score.end());
int bestCount = count(score.begin(), score.end(), bestVal);
cout << bestVal << " " << bestCount << "\n";
}
Full Solution 2:
Optionally, we can solve the problem in $O(N^22^N)$ time by reusing information across different boards instead of calculating their scores independently. In particular, if we know the score of a board and want to recalculate it after flipping one O to an M, this can be achieved in $O(N^2)$ time since there are only $O(N^2)$ distinct moos whose contributions to the score change. However, this doesn't end up being much faster than the previous solution.
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, k;
cin >> n >> k;
vector<vector<vector<int>>> isAt(n, vector<vector<int>>(n, vector<int>(n, 0)));
for (int i = 0; i < k; i++) {
int x, y, z;
cin >> x >> y >> z;
x--; y--; z--;
isAt[x][y][z]++;
}
vector<int> score((1 << n), 0);
for (int msk = 1; msk < (1 << n); msk++) {
int msb = 31 - __builtin_clz(msk);
vector<int> mpos, opos;
for (int i = 0; i < n; i++) {
if ((1 << i) & msk)
mpos.push_back(i);
else
opos.push_back(i);
}
// Previously
score[msk] = score[msk ^ (1 << msb)];
// Turned bad from flipping MSB
for (int m : mpos)
for (int o : opos)
score[msk] -= isAt[m][msb][o] + isAt[m][o][msb];
// Turned good from flipping MSB
for (int o1 : opos)
for (int o2 : opos)
score[msk] += isAt[msb][o1][o2];
}
int bestVal = *max_element(score.begin(), score.end());
int bestCount = count(score.begin(), score.end(), bestVal);
cout << bestVal << " " << bestCount << "\n";
}