村ごとに計算する。1番近い村が選ばれる確率、2番目に近い村が選ばれる確率、... を計算する。
これを間違わずに実装できる気がしないけれど、本番での正答率はそれなり。
ツラい。
double e_dist(int ax, int ay, int bx, int by)
{
double x = (ax - bx);
double y = (ay - by);
return sqrt(x * x + y * y);
}
class KingdomXCitiesandVillages
{
public:
double determineLength(vector <int> cX, vector <int> cY,
vector <int> vX, vector <int> vY)
{
const int C = cX.size();
const int V = vX.size();
const int F = 50 + 5;
double f[F];
f[0] = 1;
for (int i = 1; i < F; ++i) {
f[i] = f[i - 1] * i;
}
double ret = 0;
for (int i = 0; i < V; ++i) {
vector<double> ds;
double mnC = 1e128;
for (int j = 0; j < C; ++j) {
mnC = min(mnC, e_dist(vX[i], vY[i], cX[j], cY[j]));
}
for (int j = 0; j < V; ++j) {
if (i != j) ds.push_back(e_dist(vX[i], vY[i], vX[j], vY[j]));
}
sort(ds.begin(), ds.end());
for (int j = 0; j < V - 1; ++j) {
for (int k = 1; k <= (V - 1 - j); ++k) {
int l = (V - 1) - (j + 1);
double a = f[l] / f[l - (k - 1)];
double b = f[k - 1];
double c = a / b; // nCk
double prob = c * f[k] * f[V - 1 - k] / f[V];
double dist = min(mnC, ds[j]);
ret += prob * dist;
}
}
ret += mnC * f[V - 1] / f[V];
}
return ret;
}