マッチング。
const int TOP = 100 + 5;
const int BOT = 100 + 5;
const int N = TOP + BOT + 5;
vector<int> g[N];
int match[N];
bool vis[N];
bool rec(int curr)
{
vis[curr] = true;
for (int i = 0; i < g[curr].size(); ++i) {
int next = g[curr][i];
int w = match[next];
if (w < 0 || (!vis[w] && rec(w))) {
match[curr] = next;
match[next] = curr;
return true;
}
}
return false;
}
int matching(int n)
{
int f = 0;
fill(match, match + N, -1);
for (int i = 0; i < n; ++i) {
if (match[i] < 0) {
fill(vis, vis + N, false);
f += rec(i);
}
}
return f;
}
class PointyWizardHats {
public:
int getNumHats(vector <int> tH,
vector <int> tR,
vector <int> bH,
vector <int> bR)
{
fill(g, g + N, vector<int>());
fill(vis, vis + N, false);
const int T = tH.size();
const int B = bH.size();
const double eps = 1e-8;
for (int i = 0; i < T; ++i) {
for (int j = 0; j < B; ++j) {
double tA = (double)tR[i] / sqrt(tR[i] * tR[i] + tH[i] * tH[i]);
double bA = (double)bR[j] / sqrt(bR[j] * bR[j] + bH[j] * bH[j]);
if (tA + eps < bA && tR[i] < bR[j]) {
int a = i;
int b = j + TOP;
g[a].push_back(b);
g[b].push_back(a);
}
}
}
return matching(T);
}
};