はるのぶろぐ。

情報系大学生ハルが、ゆるゆるとIT関係についてや日々の雑記を綴ります。ちょっとだけ、あなたの役に立てる、そんなブログを目指しています。

【AtCoder】超初心者のためのデンソークリエイトプログラミングコンテスト2022C問題の解説【C言語】【ABC239】

参加してます!ポチッとお願いします

記事名と
URLをコピー

こんにちは、情報系大学生のハル(Blog_IT_haru)です。

今回は、C言語でのデンソークリエイトプログラミングコンテスト2022(AtCoder Beginner Contest 239,ABC239)に参加したので、自分の復習を兼ねてまとめていきたいと思います。

なお、私は灰色coderで、まださほど参加したことがありません。

超初心者ですので、備忘録的にまとめていきます。

f:id:Blog_IT:20220220172539p:plain

問題

C問題 Knight Fork

入力として、x1,y1,x2,y2を受け取り、xy座標平面上の2つの格子点 (x1,y1​),(x2,y2)からの距離がともに√5​である格子点は存在するか?をYesかNoで出力する。

制約:x1,y1,x2,y2はそれぞれ、−109以上、109以下であり、すべて整数。

以下より問題が確認できます。

C - Knight Fork

私の考え方

今回は、B問題の型でつまづき、A,B問題の2完だったため、私の考え方は省略します。

コンテスト終了後、公式の解説・考え方を参照し、解いたので、厳密には私の考え方でないためです。

公式の解説・考え方

今回、2つの格子点からの距離が、√5であるところのみで良いかつ、入力は、すべて整数であるため、(x1,y1)を中心とした4×4四方に含まれる点のみを調べれば良いです。

つまり、for文で、xを、x1-2以上x1+3未満まで、yをy1-2以上y1+3未満まで回せば良いことになります。

詳しくは、以下のURLよりご確認ください。

Editorial - Denso Create Programming Contest 2022(AtCoder Beginner Contest 239)

公式の考え方のコード

以下が公式の考え方でのコードになります。

公式の考え方では、C++なので、C言語ver.で、コードを書きました。

ACを取れていますので、ご安心ください。

#include <stdio.h>
long long dist_sq(a,b,c,d){
    return (a-c)*(a-c)+(b-d)*(b-d);
} long long solve(x1,y1,x2,y2){
    for(int x=x1-2;x<x1+3;x++){
        for(int y=y1-2;y<y1+3;y++){
            if(dist_sq(x,y,x1,y1) == 5 && dist_sq(x,y,x2,y2)== 5){
                return 1;
            }
        }
    }
    return 0;
} int main(void){
    long long x1=0,y1=0,x2=0,y2=0;
    scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2);
    if(solve(x1,y1,x2,y2)==0){
        printf("No\n");
    }
    else if(solve(x1,y1,x2,y2)==1){
        printf("Yes\n");
    }
}

必要な知識

以下の知識が必要です。

※各項目をクリックすることで、該当の部分に飛べます。

scanfでの値の読み取る方法

if文の使い方

printfの使い方

for文の使い方

関数の作り方と使い方

scanfで値を読み取る方法

今回は、整数なので、以下の様に読み取ります。

    int a;
scanf("%d",&a);

intは、型の種類の一つで、整数を取り扱います。

簡単に言うと、大きさが大きくない整数を取り扱える型です。

int型を、scanfで読み取るときの変換指定子は、dです。

変換指定子を簡単に言うと、整数を読み取るためのものです。

scanf自体は、scanf(”書式文字列”, &変数名1, &変数名2…)というふうに使用します。

書式文字列の中に、%dなどの変換指定子を書きます。

使い方は以下のような感じです。

int a;
scanf("%d",&a);

if文の使い方

過去に、if文について書いていた記事がありましたので、一部引用しました。

ifという文字通り、「~なら~する」という、条件で処理を実行するか否か決めることができます。

次のように使います。

if (条件式) 処理 ;

または、

if(条件式){
  処理;
}

です。

(引用元:C言語で最大値を求める - ハルの初心者プログラミング部

ただ、私の考え方で解く場合はelse ifの知識も必要です。

以下のように使用します。

ifは最初の1つだけ、elseも最後の1つだけですが、else ifは何回でも使用することができます。

    if(条件式){
        /*実行すること*/
    }
    else if(条件式){
        /*実行すること*/
    }
    else{
        /*実行すること*/
    }

printfの使い方

過去に、printfについて書いていた記事がありましたので、一部引用しました。

printfは、文字列を表示するための関数です。

普通は、以下のように、文字列を記述するのですが、今回は整数の計算結果を記述したいので、少し違う書き方になりましたね。

普通の文字列の場合

printf("tameshi");

整数の場合

printf("%d",sum);

このとき出てきた、%dのdが、変換指定子dです。

%d

printf内で使います。

整数を10進数で出力します。

int型に対応します。

使用例

printf("%d",10);

この場合、10と出力されます。

\n

printf内で使います。

改行を行います。

先程の変換指定子の前か後に記入します。

前に記入した場合は前が改行され、後ろに記入した場合は後ろが改行されます。

今回も、見やすく出力するために、使用しました。

printf("\n%d",sum);

こんな感じですね。

(引用元:C言語で合計値を求める - ハルの初心者プログラミング部

for文の使い方

同じ処理を繰り返したいときに使用する関数です。

似たような機能をもつ関数として、while文もありますが、今回は、省略します。

for文は、以下のように記述します。

for(初期値;繰り返し条件;変化式){
繰り返したい動作
}

今回はi=0から、i<5のときfor文の中身である足し算を繰り返すという処理を行いました。

より詳しく知りたい方は、こちらからどうぞ。

繰り返しを行う文 - 苦しんで覚えるC言語

関数の作り方と使い方

今回のコードでは、関数というものを用いています。

普通のC言語のコードでは、int main(void)のみであると思いますが、今回は、関数を用いることで、コードをわかりやすくしています。

今回の問題では、距離を求めるための、int型を返す、dist_sqという関数と、YesかNoを判定する、solveという関数を用いています。

関数は、以下のような形で作ります。

たまに、型名をvoidとして、返り値が無いものもありますが、今回は、どちらも返り値があるものとなっています。

型名 関数名(引数1,引数2,....){
        /*処理*/
      return 型名の型の値;
}

おすすめな記事

ABC238の、A,B,C問題の解説の記事もありますので、ぜひ読んでみてください。

他にも、ABC239のA,B問題の解説記事もあります。

blog-it.hatenablog.com

blog-it.hatenablog.com

blog-it.hatenablog.com

まとめ

いかがでしたか?

今回のC問題は簡単であったと思います。

さほど難しい考え方は使わず、素直に考えればできたと思います。

\ほんとの初心者の方は、本で学ぶのもおすすめ!/

以下の記事でおすすめ本紹介しています!

blog-it.hatenablog.com

この記事がいいな、と思ってくれたら、SNSなどで拡散したり、

ブックマークやコメントなどしてくれると励みになります!

下の方とサイドバーにある、サポートもお待ちしています!

更に、読者になってくれたら、お返しに私も読者になります!

また、この記事の内容についてなにかありましたら、

お問い合わせ、コメント、TwitterのDMなどによろしくお願いします。

それでは。