POJ 2420 A Star not a Tree?
問題
二次元座標上に点がN個与えられる。この座標上から一点を指定し、N個の点との距離の総和を最小化せよ。
やりかた
解析的に答えが求まりそうにないので、数理最適化。自分は最急降下法でやった。
選んだ座標をとし、与えられたN個の点の座標をすると距離の総和はとなる。
なのでこの関数の勾配方向は
となるので、ここから更新式に従って予め決めた回数だけX, Yを更新する。
関数が凸関数でないような気がしたため、局所最小値に入ってしまうかもしれないと思ったが、初期値を重心にすれば大丈夫だろとたかをくくって出した。
以下ソース。
int x[100], y[100]; int main(){ int N; cin >> N; double sumX = 0, sumY = 0; for(int i = 0; i < N; i++){ cin >> x[i] >> y[i]; sumX += x[i], sumY += y[i]; } double X = sumX / N; double Y = sumY / N; for(int i = 0; i < 100000; i++){ double alpha = 1e-2; double dx = 0, dy = 0; for(int j = 0; j < N; j++){ dx += (X - x[j]) / sqrt(pow(X - x[j], 2.0) + pow(Y - y[j], 2.0)); dy += (Y - y[j]) / sqrt(pow(X - x[j], 2.0) + pow(Y - y[j], 2.0)); } X = X - alpha * dx; Y = Y - alpha * dy; } double L = 0; for(int j = 0; j < N; j++) L += sqrt(pow(X - x[j], 2.0) + pow(Y - y[j], 2.0)); printf("%d\n", (int)(L + 0.5)); return 0; }
最初、学習率が小さすぎて最小値までたどりつかずWA。提出する前は収束するかきちんと確かめた上で、制限時間内で収束するような学習率にするべきだとわかった。(あたりまえだが)
Get up! 明日のSUPER ST@R!