2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

記事投稿キャンペーン 「2024年!初アウトプットをしよう」

31歳の元保守運用エンジニアがAtCoder参加してみた 3回目

Last updated at Posted at 2024-01-07

はじめに

ABC335に参加したのでその振り返り。

A問

今回のA問は、単純だったが少し悩んだ。
というのもC++の関数について知識がなかったため。
回答内容は以下。

ソースコード
A.cpp
#include<bits/stdc++.h>

using namespace std;

int main(void){
    string S;
    cin >> S;

    S.pop_back();

    cout << S << "4" << endl;

}

標準入力からSを受け取り、それの最後の文字を"4"に置き換える。
"2023"→"2024"でなく、文字通り末尾のみ変更すればよい。
末尾のみ削除する関数があったはず、という記憶があったのでググってみたところ
pop_back()関数についての記事を発見。

15分ほどで提出し、AC(正解)。
公式解説にあったpush_back()関数については全く知らなかったため、上記のように出力の際に"4"を結び付けておくようにした。
C++についての知識が欠乏しているので、AtCoder公式が用意してくれている以下教材を学んでいきたいところ。

B問

今回は比較的簡単だった。本番で初めてB問が解けた。 やったね。
回答内容は以下。

ソースコード
B.cpp
#include<bits/stdc++.h>

using namespace std;

int main(void){
    int N;
    cin >> N;

    for(int i = 0; i <= N; ++i){
        for(int j = 0; j <= N; ++j){
            for(int k = 0; k <= N; ++k){
                int l = i + j + k;
                if(l <= N){
                    cout << i << " " << j << " " << k << endl;
                }
            }
        }
    }
}

標準入力からNを受け取り、x + y + z ≦ N となるx, y, zを求める。
N ≦ 21、ということで3重ループにして計算させても、リソースへの負担は少量で済む。
つまり全探索でOK。
辞書的に小さい順で組み合わせを出力するのが条件なので、
zが最も内側の入れ子になるようにループを用意してあげればよい。
一番内側のループで変数lを宣言してやり、それがN以下であれば出力するように。
今回のB問はそこまで難しくなかった。
終わって気づいたが、for文内の各変数、x, y, zとそのまま設定した方が可読性が高かったと思う。

C問

初のC問挑戦となった。
過去問でもまだC問は手を付けていなかったため、ぶっつけ本番。
結果から言うと、時間内に回答できなかった。
回答内容は以下。

警告
勿論ですが以下のコードを実行しても解けません!

ソースコード
C.cpp
#include<bits/stdc++.h>

using namespace std;

class Point
{
    public:
        int x;
        int y;

        Point() {}    // 初期化は何もしない

        Point(int x0, int y0)
        {
            x = x0;
            y = y0;
        }

        Point operator + (const Point& p0) const
        {
            Point p1;
            p1.x = x + p0.x;
            p1.y = y + p0.y;
            return p1;
        }

        void answer()
        {
            cout << x << " " << y << endl;
        }
};

int main(void){
    int N_numberOfParts;
    int Q_numberOfQuery;

    cin >> N_numberOfParts >> Q_numberOfQuery;

    vector<Point> positionOfParts(N_numberOfParts);
    for(int i = 1; i <= N_numberOfParts; ++i){
        Point p(i, 0);
        positionOfParts.push_back(p);
    }

    vector<vector<string>> query(Q_numberOfQuery, vector<string>(1));
    for (int i = 0; i < Q_numberOfQuery; ++i){
        cin >> query[Q_numberOfQuery][0] >> query[Q_numberOfQuery][1];
    }

    for(int i = 0; i < Q_numberOfQuery; ++i){
        if(query[i][0] == "1"){
            if(query[i][1] == "R"){
                for(int j = N_numberOfParts - 1; j >= 1; --j){
                    positionOfParts[j - 1] = positionOfParts[j];
                }
                Point q(1, 0);
                positionOfParts[0] = positionOfParts[0] + q;
            }else if(query[i][1] == "L"){
                for(int j = N_numberOfParts - 1; j >= 1; --j){
                    positionOfParts[j - 1] = positionOfParts[j];
                }
                Point q(-1, 0);
                positionOfParts[0] = positionOfParts[0] + q;
            }else if(query[i][1] == "U"){
                for(int j = N_numberOfParts - 1; j >= 1; --j){
                    positionOfParts[j - 1] = positionOfParts[j];
                }
                Point q(0, 1);
                positionOfParts[0] = positionOfParts[0] + q;
            }else if(query[i][1] == "D"){
                for(int j = N_numberOfParts - 1; j >= 1; --j){
                    positionOfParts[j - 1] = positionOfParts[j];
                }
                Point q(0, -1);
                positionOfParts[0] = positionOfParts[0] + q;
            }
        }
        else{
            int m = stoi(query[i][1]);
            positionOfParts[m].answer();
        }
    }

    return 0;
}

考え方として、Pointというクラスを作成し、各パーツの位置を座標点としてインスタンスで保持させようとした。
以下の記事が参考になった。

あとはクエリの内容を判別し、頭をどの方向へ向かわせるかを決定。
そして残りのパーツの座標をひとつ前のパーツが持っていた情報に更新する……という流れ。
時間内に何とか間に合わせたかったが、時間切れ。

解説を見て

2024/01/09追記

ただ、公式解説によるとdequeなる要素が用いられていた。
ここでもC++の知識がないことが足を引っ張った。
その理解は後回しにするとして、とりあえず自分なりの解法を完成させてみた。

ソースコード
C_fixed.cpp
#include <iostream>
#include <vector>
using namespace std;

class Point {
public:
    int x;
    int y;

    Point() : x(0), y(0) {}

    Point(int x0, int y0) : x(x0), y(y0) {}

    Point operator+(const Point& p0) const {
        return Point(x + p0.x, y + p0.y);
    }

    void answer() {
        cout << x << " " << y << endl;
    }
};

int main() {
    int N_numberOfParts;
    int Q_numberOfQuery;

    cin >> N_numberOfParts >> Q_numberOfQuery;

    vector<Point> positionOfParts;
    for (int i = 0; i < N_numberOfParts; ++i) {
        Point p(i + 1, 0);
        positionOfParts.push_back(p);
    }

    vector<vector<string>> query(Q_numberOfQuery, vector<string>(2));
    for (int i = 0; i < Q_numberOfQuery; ++i) {
        cin >> query[i][0] >> query[i][1];
    }

    for (int i = 0; i < Q_numberOfQuery; ++i) {
        if (query[i][0] == "1") {
            if (query[i][1] == "R") {
                for (int j = N_numberOfParts - 1; j >= 1; --j) {
                    positionOfParts[j] = positionOfParts[j - 1];
                }
                Point q(1, 0);
                positionOfParts[0] = positionOfParts[0] + q;
            } else if (query[i][1] == "L") {
                for (int j = N_numberOfParts - 1; j >= 1; --j) {
                    positionOfParts[j] = positionOfParts[j - 1];
                }
                Point q(-1, 0);
                positionOfParts[0] = positionOfParts[0] + q;
            } else if (query[i][1] == "U") {
                for (int j = N_numberOfParts - 1; j >= 1; --j) {
                    positionOfParts[j] = positionOfParts[j - 1];
                }
                Point q(0, 1);
                positionOfParts[0] = positionOfParts[0] + q;
            } else if (query[i][1] == "D") {
                for (int j = N_numberOfParts - 1; j >= 1; --j) {
                    positionOfParts[j] = positionOfParts[j - 1];
                }
                Point q(0, -1);
                positionOfParts[0] = positionOfParts[0] + q;
            }
        } else {
            int m = stoi(query[i][1]);
            positionOfParts[m - 1].answer();
        }
    }

    return 0;
}

入力例と共に実行してみると、正しい出力例が出た!
やったねと思って提出してみると、残念ながら一部の回答でTLE(実行時間制限超過)
恐らく各パーツごとにインスタンスを生成してしまっているから、
問題によってはメモリを食ってしまっている模様。
ACになっている回答もあり、それは実行時間・メモリ共に負荷が低かったため、そのように想定。
最近はC問からアルゴリズムを活用しないと解けない、と耳にしたので、
その洗礼を受けた形だった。
ともかく自分なりのupsolveはできた。

振り返り

今回のABCでは、初めて試験時間ずっとエディタとにらめっこしていた。
これまで大抵、問題が解けなくなったことで気分転換に家事など挟んでいた。
それが今回はずっとコーディングに向かい合うことができた。
少し進歩したかもしれない。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?