凸レーダーチャート問題

解答例です。言語はC++

#include <bits/stdc++.h>
using namespace std;

bool test(vector <int> a){
    
    bool ok = true;
    int ab, ac;
    
    for(int j=0; j<6; j++){
        ab = a[(j+1)%6];
        ac = a[(j+5)%6];
        if(a[j%6]<=ab*ac/(ab+ac)){
            ok = false;
            break;
        }
    }
    
    return ok;
}

int all(vector<int> a, int n){
    
    if(n==0)
        return test(a);
    
    int k;
    
    for(int i=0; i<5; i++){
        a[n-1] = i+1;
        k += all(a, n-1);
    }
    
    return k;
}

int main(){
    
    vector<int> a(6);
    
    cout << all(a,6) << endl;
    return 0;
}


コードの心臓は \tt test関数で、すべての要素のスコア a_iが「隣り合うスコアを結んだ時の線分と要素 iの軸の交点のスコア d_i」より大きければ \tt trueを返します。1個でも成り立たなければ \tt falseです。
f:id:Callinx2You:20200419062628p:plain
(右の白点がレーダーチャートの中心。ぐるり一周あるうちの3要素だけに注目している。)

 d_iは、角の二等分線の性質を使って  d_i = a_{i-1}\hspace{2pt}a_{i+1}\hspace{2pt}/\hspace{2pt}(a_{i-1}+a_{i+1}) *1と求められます。

 \tt all関数で全てのレーダーチャートの結果について \tt test を行い、 \tt trueの個数を数えます。

計算の結果、答えは  4657通りです。

*1:これは二等分すべき角を  A として、  d_i = 2\cos(A/2)\hspace{3pt}a_{i-1}\hspace{2pt}a_{i+1}\hspace{2pt}/\hspace{2pt}(a_{i-1}+a_{i+1}) であるのを A=2\pi/3= 2\times 2\pi/6とした特殊なケースです。 一般にM段階N要素のレーダーチャートの場合を考えましょう。 N<3の場合、レーダーは多角形にならないので 0通りです。 N=3の場合、 a_i=0 なる  i が 1個までなら三角形になるので 答えは M^3 + 3M^2通りです。 N>3の場合、 d_i = 2\cos(\frac{2\pi}{N})\hspace{3pt}a_{i-1}\hspace{2pt}a_{i+1}\hspace{2pt}/\hspace{2pt}(a_{i-1}+a_{i+1}) として上のコードを一般化し、計算機をブン回せば \mathcal{O}(M^N)で求まるはずです。一般式や対称性を使えばもっと速いのかもしれませんが。