SRM 668 Div2 Medium IsItASquare

TopCoder Statistics - Problem Statement

  • 本番では自作の points class みたなのでごちゃごちゃやっていた。
  • 絶対もっと簡単に書けるだろうなと思っていたらTopCoder SRM 668 Div2 Medium IsItASquare - kmjp's blogとかみつけたので参照にしてコードを書いてみた。
class IsItASquare {
public:
string isSquare(vector <int> x, vector <int> y) {

        set<pair<int,int>> S;
        REP(i,4)
            S.emplace(x[i],y[i]);

        FOR(i,1,4)
        {
            // ベクトル X = x[0]x[i] を一つ定める
            int dx = x[i]-x[0];
            int dy = y[i]-y[0];

            // そのベクトルを 90 度回転させた位置(x0+X,xi+X それぞれ)に残りの点があればよい
            // 全ベクトルを総当りするので -90 度回転は考えなくてよい。
            if (S.count({x[0]-dy,y[0]+dx}) == 0)
                continue;
            if (S.count({x[i]-dy,y[i]+dx}) == 0)
                continue;
            return "It's a square";
        }
        return "Not a square";
}
};
  • arena では長さに注目した解答もあった。
  • 以下はそのコードを参照にしてみたもの。
class IsItASquare {
public:
    int sqr(int x, int y) { return x*x + y*y; }
    bool check(const vector<int> &dist) {
            assert(dist.size()==6);// 対角線を含め 6 本の辺
            // dist は長さ順でソート済みなので、正方形なら最初の 4 つは長さが同じはず
            REP(i,4)
            {
                if (dist[i] != dist[0])
                    return false;
            }
            // 正方形なら対角線の長さは同じはず
            if (dist[4] != dist[5])
                return false;
            // 対角線の長さと各辺の長さの関係をチェック
            return (dist[0]*2==dist[4]);
    }
string isSquare(vector <int> x, vector <int> y) {
        vector<int> dist;
        REP(i,4)
        FOR(j,i+1,4)
        {
            // 各点の距離の二乗を入れる
            dist.push_back(sqr(x[i]-x[j],y[i]-y[j]));
        }
        sort(RANGE(dist));
        if (check(dist))
            return "It's a square";
        else
            return "Not a square";
}
};