AtCoder - ABC#1 C言語

A問題

 この問題は問題文の通りに積雪量の差を求めて出力すれば解ける。

#include <stdio.h>

int main() {
  int h_after, h_before;
  scanf("%d", &h_after);
  scanf("%d", &h_before);
  printf("%d\n", h_after - h_before);
  return 0;
}

B問題

 この問題も問題文の通りに条件分岐をかければ解ける。少し工夫をするのであれば、単位をkmではなくmに合わせることで小数を使わずに実装することぐらい。

#include <stdio.h>

int main() {
  int meter, VV;
  scanf("%d", &meter);
  if(meter < 100) {
    VV = 0;
  } else if(100 <= meter && meter <= 5000) {
    VV = meter / 100;
  } else if(6000 <= meter && meter <= 30000) {
    VV = meter /1000 + 50;
  } else if(35000 <= meter && meter <= 70000) {
    VV = (meter - 30000) / 5000 + 80;
  } else if(70000 < meter) {
    VV = 89;
  }
  printf("%02d\n", VV);
  return 0;
}

C問題

 この問題も問題文にある通りの条件分岐を書いて、四捨五入さえ忘れなければ解けるだろう。

#include <stdio.h>

int main() {
  int wind_direction, wind_power;
  scanf("%d %d", &wind_direction, &wind_power);
  if(wind_power < 0.25 * 60) {
    printf("C ");
  } else if(112.5 <= wind_direction && wind_direction < 337.5) {
    printf("NNE ");
  } else if(337.5 <= wind_direction && wind_direction < 562.5) {
    printf("NE ");
  } else if(562.5 <= wind_direction && wind_direction < 787.5) {
    printf("ENE ");
  } else if(787.5 <= wind_direction && wind_direction < 1012.5) {
    printf("E ");
  } else if(1012.5 <= wind_direction && wind_direction < 1237.5) {
    printf("ESE ");
  } else if(1237.5 <= wind_direction && wind_direction < 1462.5) {
    printf("SE ");
  } else if(1462.5 <= wind_direction && wind_direction < 1687.5) {
    printf("SSE ");
  } else if(1687.5 <= wind_direction && wind_direction < 1912.5) {
    printf("S ");
  } else if(1912.5 <= wind_direction && wind_direction < 2137.5) {
    printf("SSW ");
  } else if(2137.5 <= wind_direction && wind_direction < 2362.5) {
    printf("SW ");
  } else if(2362.5 <= wind_direction && wind_direction < 2587.5) {
    printf("WSW ");
  } else if(2587.5 <= wind_direction && wind_direction < 2812.5) {
    printf("W ");
  } else if(2812.5 <= wind_direction && wind_direction < 3037.5) {
    printf("WNW ");
  } else if(3037.5 <= wind_direction && wind_direction < 3262.5) {
    printf("NW ");
  } else if(3262.5 <= wind_direction && wind_direction < 3487.5) {
    printf("NNW ");
  } else {
    printf("N ");
  }

  if(wind_power < 0.25 * 60) {
    printf("0\n");
  } else if(wind_power < 1.55 * 60) {
    printf("1\n");
  } else if(wind_power < 3.35 * 60) {
    printf("2\n");
  } else if(wind_power < 5.45 * 60) {
    printf("3\n");
  } else if(wind_power < 7.95 * 60) {
    printf("4\n");
  } else if(wind_power < 10.75 * 60) {
    printf("5\n");
  } else if(wind_power < 13.85 * 60) {
    printf("6\n");
  } else if(wind_power < 17.15 * 60) {
    printf("7\n");
  } else if(wind_power < 20.75 * 60) {
    printf("8\n");
  } else if(wind_power < 24.45 * 60) {
    printf("9\n");
  } else if(wind_power < 28.45 * 60) {
    printf("10\n");
  } else if(wind_power < 32.65 * 60) {
    printf("11\n");
  } else {
    printf("12\n");
  }
  return 0;
}

別解

 基本的には条件分岐をもれなく書けば解けるが、条件分岐の数が多すぎる。条件分岐の数が多いほどバグを含んだコードになりやすいためここではif文を少なくしたものを書いてみた。あらかじめ方角を表す文字列を配列として作っておくことでifを1つにまとめることができる。
 また、風力の出力では、境界となる値を格納した配列を使うことでif文を1つにまとめている。
 こちらの方がコンパクトで見やすいですよね。こんな感じで使う条件分岐は極力少なくを意識しよう。

#include <stdio.h>

int main() {
  int wind_direction, wind_power, direction_flag, i = 0;
  double wind_power_border[12] = {0.25*60, 1.55*60, 3.35*60, 5.45*60, 7.95*60, 10.75*60, 13.85*60, 17.15*60, 20.75*60, 24.45*60, 28.45*60, 32.65*60};
  char direction_mark[18][4] = {"C", "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW", "N"};
  scanf("%d %d", &wind_direction, &wind_power);
  if(wind_power >= 0.25 * 60) {
    for(i = 1; i < 18; i++) {
      if(wind_direction < 225 * i - 112.5) {
        break;
      }
    }
  }
  printf("%s ", direction_mark[i]);

  for(i = 0; i < 12; i++) {
    if(wind_power < wind_power_border[i]) {
      break;
    }
  }
  printf("%d\n", i);
  return 0;
}

D問題

 この問題は1日の中で、雨が降り始めた時刻と止んだ時刻を出力しなければならない。また与えられる入力値は、時刻が重複することがある。この問題ではすべき処理がいくつかある。
 最初にすべきなのは、時刻を5分刻みに直す処理である。そのあとに雨の降っていた時間をまとめて、最後にまとめたものを調べて出力をする処理が必要である。
 忘れがちなのは5分刻みに丸めた時に下二桁が60分になったときに60分を1時間に変換する作業ですね。
あとは、配列を作って雨が降っていた間の時刻は全て1で埋めるようにしてあげれば下のソースコードのようになる。

#include <stdio.h>

int main() {
  int times_rainy /*メモ上の雨が降った回数*/, i, j, start_time, end_time, temp = 1;
  scanf("%d", &times_rainy);
  int time[2402] = {}; //配列の要素を0で初期化
  for(i = 0; i < times_rainy; i++) {
    scanf("%d-%d", &start_time, &end_time);
    start_time -= (start_time % 5); //5分刻みに
    end_time = end_time + (((end_time % 5) == 0)? 0 : (5 - (end_time % 5))); //5分刻みに
    if((start_time % 100) == 60 /*60分を1時間に置き換え*/) {
      start_time += 40;
    }
    if((end_time % 100) == 60/*60分を1時間に置き換え*/) {
      end_time += 40;
    }
    for(j = start_time; j < end_time; j++) {
      time[j] = 1; /*雨が降り始めた時刻から止む直前の時刻までを1でマーク*/
    }
  }
  for(i = 0; i <= 2400; i++) {
    if(temp == time[i] && temp == 1 /*雨が降り始めた時刻を表示*/) {
      temp = 0;
      printf("%04d-", i);
    } else if(time[i] == temp && temp == 0 /*雨が止んだ時刻を表示*/) {
      temp = 1;
      printf("%04d\n", i);
    }
  }
  return 0;
}


最後まで見ていただきありがとうございます。また別の記事でお会いできることを祈っております。