Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

AtCoder Beginner Contest 004 解説

9,189 views

Published on

AtCoder Beginner Contest 004の解説です。

Published in: Education
  • Be the first to comment

AtCoder Beginner Contest 004 解説

  1. 1. AtCoder Beginner Contest #004 解説資料 2014年 2月 16日 AtCoder株式会社 青木謙尚 ©AtCoder Inc. All rights reserved. 1
  2. 2. 目次 1. 競技プログラミングを始める前に 2. A~D問題 • ところどころに入出力の方法があります ©AtCoder Inc. All rights reserved. 2
  3. 3. 競技プログラミングを始める前に ©AtCoder Inc. All rights reserved. 3
  4. 4. 競技プログラミングを始める前に (競技)プログラミングを始めたいけど、 そもそもプログラムって何をするの? ©AtCoder Inc. All rights reserved. 4
  5. 5. 競技プログラミングを始める前に • (競技)プログラミングを始めたいけど、そもそもプロ グラムって何をするの? • 大雑把に言うと 1. 情報を受け取って 情報 プログラム ©AtCoder Inc. All rights reserved. 5
  6. 6. 競技プログラミングを始める前に • (競技)プログラミングを始めたいけど、そもそもプロ グラムって何をするの? • 大雑把に言うと 1. 情報を受け取って 情報 プログラム 1. 何らかの処理を施して情報を加工する 情報 プログラム ©AtCoder Inc. All rights reserved. 情報 6
  7. 7. 競技プログラミングを始める前に • (競技)プログラミングを始めたいけど、そもそもプロ グラムって何をするの? • 大雑把に言うと 1. 情報を受け取って 情報 プログラム 1. 何らかの処理を施して情報を加工する プログラム 情報 1. そしてどこかへ渡す 情報 プログラム 情報 情報 ©AtCoder Inc. All rights reserved. 7
  8. 8. 競技プログラミングを始める前に • 具体例  検索 くおえうえーーーるえうおおお ©AtCoder Inc. All rights reserved. 可愛い 8
  9. 9. 競技プログラミングを始める前に • 具体例  検索 くおえうえーーーるえうおおお 受け取る ©AtCoder Inc. All rights reserved. 可愛い Gaagle 9
  10. 10. 競技プログラミングを始める前に • 具体例  検索 くおえうえーーーるえうおおお 受け取る 可愛い Gaagle 検索という処理 検索結果 ©AtCoder Inc. All rights reserved. 10
  11. 11. 競技プログラミングを始める前に • 具体例  検索 くおえうえーーーるえうおおお 受け取る 可愛い Gaagle 検索という処理 結果を渡す ©AtCoder Inc. All rights reserved. 検索結果 11
  12. 12. 競技プログラミングを始める前に • 入出力ができなければ、 • “くおえうえーーーるえうおおお 可愛 い” • を受け取れないし、 • 検索結果も渡せない ©AtCoder Inc. All rights reserved. 12
  13. 13. 競技プログラミングを始める前に • 入出力ができなければ、 • “くおえうえーーーるえうおおお 可愛 い” • を受け取れないし、 • 検索結果も渡せない • アルゴリズムより先にすることがある! • 本当に本当に始めたばかりの人へ • まずは入出力から始めませんか? ©AtCoder Inc. All rights reserved. 13
  14. 14. A問題 1. 問題概要 2. 入力 3. 処理(アルゴリズム) 4. 出力 ©AtCoder Inc. All rights reserved. 14
  15. 15. A問題 問題概要 1. 整数Nが与えられる。 1. 2*Nを出力せよ。 ©AtCoder Inc. All rights reserved. 15
  16. 16. A問題 問題概要 1. 整数Nが与えられる。  入力される値であるNを保存する! 2. 2*Nを出力せよ。  保存したNに2をかけて出力する! ©AtCoder Inc. All rights reserved. 16
  17. 17. A問題 入力 • 入力の取り方は標準入出力でググってください • とはいえ、少しだけサンプルを載せます • コードの色は • 受け取り • 処理 • 出力 • を表したものではないので、注意して下さい • AtCoderへ提出したときの色です ©AtCoder Inc. All rights reserved. 17
  18. 18. A問題 入力 • C #include<stdio.h> int main(){ int N; scanf("%d", &N); return 0; } ©AtCoder Inc. All rights reserved. 18
  19. 19. A問題 入力 • C++ #include<iostream> int main(){ int N; std::cin >> N; return 0; } ©AtCoder Inc. All rights reserved. 19
  20. 20. A問題 入力 • Java import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); } } ©AtCoder Inc. All rights reserved. 20
  21. 21. A問題 入力 • C# using System; class Program{ static void Main(string[] args){ int N = int.Parse(Console.ReadLine()); } } ©AtCoder Inc. All rights reserved. 21
  22. 22. A問題 入力 • その他 • http://practice.contest.atcoder.jp/ を参照してください • たいていの言語の例があります ©AtCoder Inc. All rights reserved. 22
  23. 23. A問題 補足(変数と型について) • さきほどから入力を受け取ると何度も書いてま すが、受け取るためには保存するための入れ物 が必要です。 • プログラムの世界でも入れ物に形があります。  これを型といいます。 ©AtCoder Inc. All rights reserved. 23
  24. 24. A問題 補足(変数と型について) • 型の例  整数型 int  0, 1, 2 … 100 … などの整数  文字型 char  a, b, c … A, B … などの1文字 • 各型で表現できる最大、最小の値は言語や処理 系で変化します ©AtCoder Inc. All rights reserved. 24
  25. 25. A問題 補足(変数と型について) • 変数について  int variable = 4; 4 とすると、 variableという入れ物に4が入ります variable  さらに と variable = 1; 1 とする variableに1が上書きされます variable ©AtCoder Inc. All rights reserved. 25
  26. 26. A問題 処理(アルゴリズム) 受け取ったNに  2をかける ©AtCoder Inc. All rights reserved. 26
  27. 27. A問題 処理(アルゴリズム) 受け取ったNに  2をかける コードは以下だけ N = N * 2; ©AtCoder Inc. All rights reserved. 27
  28. 28. A問題 出力 処理の結果を出力します • C printf(“%dn”, N); • C++ cout << N << endl; ©AtCoder Inc. All rights reserved. 28
  29. 29. A問題 出力 • Java System.out.println(N); • C# Console.WriteLine(N); ©AtCoder Inc. All rights reserved. 29
  30. 30. B問題 1. 問題概要 2. 入力 3. 処理(アルゴリズム) 4. 出力 ©AtCoder Inc. All rights reserved. 30
  31. 31. B問題 問題概要 1. 4x4の盤面が与えられる。 2. 盤面を180度回転させて出力せよ。 ©AtCoder Inc. All rights reserved. 31
  32. 32. B問題 問題概要 1. 4x4の盤面が与えられる。  盤面を保存する 2. 盤面を180度回転させて出力せよ。  盤面を180度回転させる  出力する ©AtCoder Inc. All rights reserved. 32
  33. 33. B問題 問題概要 絶望ポイントその1 • 盤面の状態ってどう保存すればいいんだ!? 絶望ポイントその2 • 180度の回転ってどうやればいいんだ!? ©AtCoder Inc. All rights reserved. 33
  34. 34. B問題 問題概要 絶望ポイントその1 • 盤面の状態ってどう保存すればいいんだ!?  配列を使いましょう 絶望ポイントその2 • 180度の回転ってどうやればいいんだ!?  コピー用の配列を作る  元の配列を逆からコピーする ©AtCoder Inc. All rights reserved. 34
  35. 35. B問題 入力 まずは盤面の保存から • 配列って何? ©AtCoder Inc. All rights reserved. 35
  36. 36. B問題 入力 まずは盤面の保存から • 配列って何? 連続した箱 です • 世界で最も偉大な箱かも ©AtCoder Inc. All rights reserved. 36
  37. 37. B問題 入力 まずは盤面の保存から • 配列って何? 1つだけだと変数 連続してたら配列 ©AtCoder Inc. All rights reserved. 37
  38. 38. B問題 入力 まずは盤面の保存から • どこが偉大なの? 縦に並べることができる  これで盤面が作れる! ©AtCoder Inc. All rights reserved. 38
  39. 39. B問題 入力 まずは盤面の保存から • 配列の概念はわかったけど、何をすればいい の? ©AtCoder Inc. All rights reserved. 39
  40. 40. B問題 入力 まずは盤面の保存から • 配列の概念はわかったけど、何をすればいい の? 宣言 して下さい ©AtCoder Inc. All rights reserved. 40
  41. 41. B問題 入力 2次元配列の宣言 • C/C++ char board[4][4]; • Java char[][] board = new char[4][4]; • C# char[,] board = new[4, 4]; ©AtCoder Inc. All rights reserved. 41
  42. 42. B問題 補足(配列のアクセス方法) char array [4]; 1 array という配列を宣言する 2 a # z % すでに文字が格納されているとする 3 a # z % array[0]のようにしてアクセスでき array[0] array[2] array[1] array[3] 0から始まることに注意! ©AtCoder Inc. All rights reserved. 42
  43. 43. B問題 補足(配列のアクセス方法2) char board[2][2]; board boardという2次元配列を宣言する a board z # % 同様に、何らかの文字が入っているとする board[0][0] a # board[0][1] board[1][0] z % board[1][1] board[0][0]には board[0][1]には board[1][0]には board[1][1]には ©AtCoder Inc. All rights reserved. ’a’ ’#’ ’z’ ’%’ 43
  44. 44. B問題 処理(アルゴリズム) 180度の回転ってどうするの?  コピー用の配列を用意します。  char copy[4][4]; を宣言しておきます。  元の配列を逆からコピー用の配列に移します。  for文を使います。 ©AtCoder Inc. All rights reserved. 44
  45. 45. B問題 処理(アルゴリズム) コーディングに入る前に、いまからすることを図 示します。 1. コピー用の配列を宣言します。 char copy[4][4]; ©AtCoder Inc. All rights reserved. 45
  46. 46. B問題 処理(アルゴリズム) 2.元の配列を逆からコピー用の配列に移します。 x x x x x x x x x x x x x x x O x board copy ©AtCoder Inc. All rights reserved. 46
  47. 47. B問題 処理(アルゴリズム) 2.元の配列を逆からコピー用の配列に移します。 x x x x x x x x x x x x x x x x O x board copy ©AtCoder Inc. All rights reserved. 47
  48. 48. B問題 処理(アルゴリズム) 2.元の配列を逆からコピー用の配列に移します。 x x x x x x x x x x x x x x x x x O x board copy ©AtCoder Inc. All rights reserved. 48
  49. 49. B問題 処理(アルゴリズム) 途中を省略して… ©AtCoder Inc. All rights reserved. 49
  50. 50. B問題 処理(アルゴリズム) 2.元の配列を逆からコピー用の配列に移します。 x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x O board copy ©AtCoder Inc. All rights reserved. 50
  51. 51. B問題 処理(アルゴリズム) 2.元の配列を逆からコピー用の配列に移します。 x x x O x x x x x x x x x x x x x x x x x x board x x x x x x x x x O copy ©AtCoder Inc. All rights reserved. 51
  52. 52. B問題 処理(アルゴリズム) • 移せばよいことはわかったけど、実際にどうするの?  for文を使います。  for文とは繰り返し行われる処理を記述するもので • す。 復習  2次元配列の添字について ©AtCoder Inc. All rights reserved. 52
  53. 53. B問題 処理(アルゴリズム) • 2次元配列の添字について [0,0] [0,1] [0,2] [0,3] [1,0] [1,1] [1,2] [1,3] [2,0] [2,1] [2,2] [2,3] [3,0] [3,1] [3,2] [3,3] ©AtCoder Inc. All rights reserved. • 注意点  数学のxy座標とは 異なる  マスは4x4だが、 添字は[3,3]まで 53
  54. 54. B問題 処理(アルゴリズム) • for文のコード for(int i = 0; i < 4; i++){ for(int j = 0; j < 4; j++){ copy[i][j] = board[3-i][3-j]; } } ©AtCoder Inc. All rights reserved. 54
  55. 55. B問題 処理(アルゴリズム) for文のコード(i = 0, j = 0のとき) copy[0][0] = board[3-0][3-0]; O x x x x x x x x x x x x x x x • x copy board ©AtCoder Inc. All rights reserved. 55
  56. 56. B問題 処理(アルゴリズム) for文のコード(i = 0, j = 1のとき) copy[0][1] = board[3-0][3-1]; O x x x x x x x x x x x x x x x x • x board copy ©AtCoder Inc. All rights reserved. 56
  57. 57. B問題 処理(アルゴリズム) for文のコード(i = 0, j = 2のとき) copy[0][2] = board[3-0][3-2]; O x x x x x x x x x x x x x x x x x • x board copy ©AtCoder Inc. All rights reserved. 57
  58. 58. B問題 処理(アルゴリズム) 途中を省略して… ©AtCoder Inc. All rights reserved. 58
  59. 59. B問題 処理(アルゴリズム) for文のコード(i = 3, j = 2のとき) copy[3][2] = board[3-3][3-2]; x x x x x x x x x x x x x x x x x x x x x x x x x x x x x O x • board copy ©AtCoder Inc. All rights reserved. 59
  60. 60. B問題 処理(アルゴリズム) for文のコード(i = 3, j = 3のとき) copy[3][3] = board[3-3][3-3]; x x x O x x x x x x x x x x x x x x x x x x board x x x x x x x x O x • copy ©AtCoder Inc. All rights reserved. 60
  61. 61. B問題 出力 3.180度回転させたものを順に出力するだけ  これもforを使って書いて下さい。 x x x x x x x x x x x O x x x x copy ©AtCoder Inc. All rights reserved. 61 x
  62. 62. B問題 処理(アルゴリズム) 途中を省略して… ©AtCoder Inc. All rights reserved. 62
  63. 63. B問題 出力 3.180度回転させたものを順に出力するだけ x x x x x x x x x x x O x x x x x x x x x x x x x x x x O x x copy ©AtCoder Inc. All rights reserved. 63 x
  64. 64. C問題 1. 問題概要 2. 処理(アルゴリズム) ©AtCoder Inc. All rights reserved. 64
  65. 65. C問題 問題概要 1. 1から6までの数字が割り振られた、6枚のカー ドが左から順に整列している。 2. 整数N(1≦N≦10^9)が与えられる。 3. i=0からi=N-1までのN回、カードを入れ替え る。  左から{(i%5)+1}番目のカードと、 左から{(i%5)+2}番目のカードを入れ替える。 ©AtCoder Inc. All rights reserved. 65
  66. 66. C問題 • 補足(剰余について) 剰余演算子 % について  要は「余り」のこと  7%3 は「7を3で割った余り」を意味する  つまり1  ほとんどのプログラミング言語では%が剰余 演算子として実装されている ©AtCoder Inc. All rights reserved. 66
  67. 67. C問題 処理(アルゴリズム) 1. この問題のポイントは、Nの値に大きな値が含 まれること(最大でN=10^9まで) 2. つまり、普通に交換していくだけでは時間的な 制約上、満点を得るのは厳しい(2s以内) 3. ここに気づくことができるかが、満点を得るた めのポイント  できるだけ交換回数を減らしたい! ©AtCoder Inc. All rights reserved. 67
  68. 68. C問題 • 処理(アルゴリズム) とはいえ、まずは実験してみる 初期状態 1 i=0 2 i=1 2 2 1 3 3 4 5 6 3 4 5 6 1 4 5 6 ©AtCoder Inc. All rights reserved. 68
  69. 69. C問題 • 処理(アルゴリズム) まずは実験してみる i=2 2 3 4 1 i=3 2 3 4 5 i=4 2 3 4 5 ©AtCoder Inc. All rights reserved. 5 1 6 6 6 1 69
  70. 70. C問題 • 処理(アルゴリズム) あれ?1が右端に移動して2~6までは整列している・・・? i=4 • i=5 2 3 4 5 6 1 さらに実験してみる 3 2 4 ©AtCoder Inc. All rights reserved. 5 6 1 70
  71. 71. C問題 • 処理(アルゴリズム) さらに実験してみる i=6 3 4 i=7 3 4 5 i=8 3 4 5 5 6 ©AtCoder Inc. All rights reserved. 6 1 2 2 6 1 2 1 71
  72. 72. C問題 処理(アルゴリズム) 3 i=9 4 5 6 1 2 • 先頭から3~6が整列している。で、後ろに1と2が並んでいる。 • ということは、もっと進めてみると以下のようになるのでは? i=? 4 5 6 1 ©AtCoder Inc. All rights reserved. 2 3 72
  73. 73. C問題 • 処理(アルゴリズム) さらにさらに進めると、きっとこういった遷移が行われるはず i = ?? 5 6 1 2 3 4 i = ??? 6 1 2 3 4 5 i = ???? 1 2 3 4 5 6 ©AtCoder Inc. All rights reserved. 73
  74. 74. 処理(アルゴリズム) C問題 • iがいくつのときかはわからないけれど、初期状態に帰ってくる?  あくまでも現段階では予想である i=0 1 2 3 4 5 6 i = ???? 1 2 3 4 5 6 ©AtCoder Inc. All rights reserved. 74
  75. 75. C問題 • 処理(アルゴリズム) 確かめてみる!  方法は、カードの遷移を出力する i=0 i=1 i=2 i = 29 i = 30 213456 231456 234156 : 123456 213456 ©AtCoder Inc. All rights reserved. 発見! 75
  76. 76. C問題 • 処理(アルゴリズム) 確かめてみる!  方法は、カードの遷移を出力する 交換回数はiが 0から29までの30回 i=0 i=1 i=2 i = 29 i = 30 213456 231456 234156 : 123456 213456 カードが6枚あって、入れ替え可能な場所が5通りあるか 6 x 5 = 30回交換すると初期状態に戻る ©AtCoder Inc. All rights reserved. 76
  77. 77. C問題 • 処理(アルゴリズム) 実験の結果、30回交換すると初期状態に戻ることがわ かった。  31回の交換は、1回の交換と同じ。  32回の交換は、2回の交換と同じ。  100回の交換は?  100 mod 30 => 10 より、10回の交換と同じ  30で割ったときの余り(剰余)がポイント • Nを30で割ったときの余りで交換すればよい ©AtCoder Inc. All rights reserved. 77
  78. 78. C問題 • 処理(アルゴリズム) これでNの値が大きくなっても対応できる!  たとえば、N = 1000 のとき、実際に1000回交換す るのではなく、1000 mod 30 => 10回交換すればよ い  30で割ったときの余りは、0~29の30通りあるが、 最大でも29回ですむ。 N = N % 30; としておけばよい ©AtCoder Inc. All rights reserved. 78
  79. 79. C問題 処理(アルゴリズム) • 数値の入れ替えの仕方 • A, Bを入れ替えたい時の処理 • • A = B; • • C = A; B = C; のように、Cを中継してあげれば入れ替えることが出来 る。 • C++などは、標準でswap関数が用意されている ©AtCoder Inc. All rights reserved. 79
  80. 80. AtCoder Beginner Contest #004 解説資料 続き 2014年 2月 16日 AtCoder株式会社 高橋直大 ©AtCoder Inc. All rights reserved. 80
  81. 81. D問題 1. 問題概要 2. 処理(アルゴリズム) ©AtCoder Inc. All rights reserved. 81
  82. 82. D問題 • 問題概要 番号がついた箱が無限個並んでおり、左から順番 に、..,-2,-1,0,1,2,..と番号がついている • いくつかの箱には、マーブルが入っている。 • • 番号0の箱には、緑のマーブルがG個 • • 番号-100の箱には、赤いマーブルがR個 番号100の箱には、青いマーブルがB個 これらのマーブルを、1個隣の箱に移動することが出 来る。 • 全ての箱に、マーブルが2個以上入っていない状態に する。 ©AtCoder Inc. All rights reserved. 82
  83. 83. D問題 • 部分点1 • • R, G, B ≦ 5 部分点2 • • 問題概要 R, G, B ≦ 40 満点 • R, G, B ≦ 300 ©AtCoder Inc. All rights reserved. 83
  84. 84. D問題 • 処理(アルゴリズム) 例えば、Gが4の時 -3 -2 -1 0 1 2 ©AtCoder Inc. All rights reserved. 3 84
  85. 85. D問題 処理(アルゴリズム) • 例えば、Gが4の時 • マーブルを右に -3 -2 -1 0 1 2 ©AtCoder Inc. All rights reserved. 3 85
  86. 86. D問題 処理(アルゴリズム) • 例えば、Gが4の時 • マーブルを右に2回移動して -3 -2 -1 0 1 2 ©AtCoder Inc. All rights reserved. 3 86
  87. 87. D問題 処理(アルゴリズム) • 例えば、Gが4の時 • マーブルを右に2回移動して、さらにもう1個右に -3 -2 -1 0 1 2 ©AtCoder Inc. All rights reserved. 3 87
  88. 88. D問題 処理(アルゴリズム) • 例えば、Gが4の時 • マーブルを右に2回移動して、さらにもう1個右に • 最後に左に移動しておしまい -3 -2 -1 0 1 2 ©AtCoder Inc. All rights reserved. 3 88
  89. 89. D問題 • 処理(アルゴリズム) 部分点1は、このように、R,G,Bに対して、左右にマー ブルを振り分けてあげれば良い。 • • 深さ優先探索や、幅優先探索を使ってもOK。 部分点2も、右、左、右、左、と振り分けてあげてしま えば、R,G,Bのマーブルが40個以下、かつ、箱の数が 100個離れているので、重なることもなく、解くことが 出来る。 • 満点解法は、もう少し考察が必要。 ©AtCoder Inc. All rights reserved. 89
  90. 90. 処理(アルゴリズム) D問題 • どのマーブルを右に、どのマーブルを左に・・・と考 えるのは非常に面倒! • 最後の状態だけ考えて、そこから、その状態にするの に必要な手数を考えたい。 3 2 1 0 1 2 3 3 2 1 0 ©AtCoder Inc. All rights reserved. 1 2 3 90
  91. 91. 処理(アルゴリズム) D問題 • どのマーブルを右に、どのマーブルを左に・・・と考 えるのは非常に面倒! • 最後の状態だけ考えて、そこから、その状態にするの に必要な手数を考えたい。 • 単純に、移動距離を足し算してあげればOK! 1+1+2=4 1 3 2 1 0 1 2 3 3 2 1 2 1 0 1 ©AtCoder Inc. All rights reserved. 2 3 91
  92. 92. D問題 • 処理(アルゴリズム) R,G,Bが大きくなると・・・ : : … … ©AtCoder Inc. All rights reserved. 92
  93. 93. D問題 処理(アルゴリズム) • R,G,Bが大きくなると・・・ • 同じ広げ方をすると、被ってしまうことがある! • 単純に右、左、右、左、と考えるだけではダメ。 … … ©AtCoder Inc. All rights reserved. 93
  94. 94. 処理(アルゴリズム) D問題 • 解法1 広げ方の全探索! • 図のように、途中で間が空くことはありえない。 3 • 2 1 0 1 2 3 よって、赤・緑・青のマーブルの入っている、一番左 の箱だけ決めれば、最終状態は確定する。 • これだけだと、それぞれ可能性のある場所が1000近 くあるため、微妙に間に合わない。 • 高速な実装をすればこれでもギリギリ間に合 う。 ©AtCoder Inc. All rights reserved. 94
  95. 95. D問題 • 処理(アルゴリズム) 赤、緑、青に対して、それぞれ全て全探索をすると、 計算量が3乗になってしまい間に合わない。 • • 何か工夫が必要 緑から先に決めてあげることによって、赤と青を別々 に計算することが出来る! ©AtCoder Inc. All rights reserved. 95
  96. 96. D問題 • 処理(アルゴリズム) 例えば図のような場合 ©AtCoder Inc. All rights reserved. 96
  97. 97. D問題 処理(アルゴリズム) • 例えば図のような場合 • まず緑の広げ方を決めてあげる ©AtCoder Inc. All rights reserved. 97
  98. 98. D問題 処理(アルゴリズム) • 例えば図のような場合 • まず緑の広げ方を決めてあげる • すると、赤の広げ方、青の広げ方は、それぞれの広げ 方に干渉しない。 • よって、2乗の計算量で計算することが可能になる! ©AtCoder Inc. All rights reserved. 98
  99. 99. 処理(アルゴリズム) D問題 • 広げる時のコストは、O(1)の計算量で計算することが 可能。 • それぞれのマーブルの移動距離は、中央で区切ると 等差数列になるため、足し算が可能。 • 3,2,1,0,1,2,3,4,5,6みたいな配列になる。 ©AtCoder Inc. All rights reserved. 99
  100. 100. D問題 • 処理(アルゴリズム) そもそも、部分点2と同じ並べ方をまず試してみて、 それが収まるなら、探索する必要はない。 ©AtCoder Inc. All rights reserved. 100
  101. 101. D問題 • 処理(アルゴリズム) そもそも、部分点2と同じ並べ方をまず試してみて、 それが収まるなら、その解を採用すれば良いので、探 索する必要はない。 • 収まらないなら、限界まで中央に寄せてあげれば良い ので、こちらも探索する必要はない。 ©AtCoder Inc. All rights reserved. 101
  102. 102. D問題 処理(アルゴリズム) • 緑が中心だとダメな例! • 緑・赤が多くて、青が少ない場合。 ©AtCoder Inc. All rights reserved. 102
  103. 103. D問題 処理(アルゴリズム) • 緑が中心だとダメな例! • 緑・赤が多くて、青が少ない場合。 • 赤を跳ね飛ばすと、赤を大量に移動させないといけな くなってしまう。 ©AtCoder Inc. All rights reserved. 103
  104. 104. D問題 処理(アルゴリズム) • 緑が中心だとダメな例! • 緑・赤が多くて、青が少ない場合。 • 赤を跳ね飛ばすと、赤を大量に移動させないといけな くなってしまう。→緑を右に移動してあげないといけ ない! ©AtCoder Inc. All rights reserved. 104
  105. 105. D問題 処理(アルゴリズム) • 解法2 動的計画法を使おう! • 左の箱から順番に、「赤を置く」「緑を置く」「青を 置く」「置かない」の4通りの全探索が考えられる。 • 範囲は適当に-1000から+1000の箱までやるとして、 2000回程度の分岐 • このまま全探索すると、4^2000程度の計算量 • これを、動的計画法orメモ化再帰をしてあげること により、解いてあげる。 ©AtCoder Inc. All rights reserved. 105
  106. 106. D問題 • 処理(アルゴリズム) まず、一番左に対して4つの分岐 ©AtCoder Inc. All rights reserved. 106
  107. 107. D問題 • 処理(アルゴリズム) まず、一番左に対して4つの分岐 ©AtCoder Inc. All rights reserved. 107
  108. 108. D問題 処理(アルゴリズム) • 動的計画法・メモ化再帰とは? • 一度計算したものを、二度計算しなかったり、同じも のを纏めて計算してあげることにより、計算量を大幅 に削減してあげるテクニック ©AtCoder Inc. All rights reserved. 108
  109. 109. D問題 • 処理(アルゴリズム) 今回の場合は、左から順番に探索してあげるとして、 • • 赤いマーブルがいくつ残っているか • 緑のマーブルがいくつ残っているか • • どの箱を見ているか 青のマーブルがいくつ残っているか しか状態が存在しない。 ©AtCoder Inc. All rights reserved. 109
  110. 110. D問題 処理(アルゴリズム) • 動的計画法の場合 • 適当な4次元配列dpを用意する • dp[今見ている場所][赤の残り数][緑の残り数][青の残り 数] • これに対して、「この状況になるための最小の移動 数」を格納してあげるような、計算の省略を行う。 ©AtCoder Inc. All rights reserved. 110
  111. 111. D問題 処理(アルゴリズム) • 深さ優先探索を利用したメモ化再帰の場合 • int dfs(今見ている場所,赤の残り数,緑の残り数,青の残り 数)のような再帰関数を作る。 • 返り値は、その先で全てのマーブルを配置するため に必要な移動数 ©AtCoder Inc. All rights reserved. 111
  112. 112. D問題 • 処理(アルゴリズム) このように動的計画法・メモ化再帰を行うと、それぞ れの状態数は、2000 * 300 * 300 * 300程度存在し、そ れぞれに対して分岐の数が4つ。 • これでは計算量が大きすぎる! • もう少し工夫をしてあげる必要がある。 ©AtCoder Inc. All rights reserved. 112
  113. 113. D問題 • 処理(アルゴリズム) 考察をすることで、計算量を削減しよう! • 先ほどは、「赤を置く」「緑を置く」「青を置く」 の3通りの置き方を考慮していた。 • しかし、左から順番に、赤・緑・青と並ぶのが自然 であり、赤が置けるなら緑・青を置く必要はない し、緑が置けるなら青を置く必要はない。(今回の 問題設定では出来ない!) • つまり、分岐の数を4つから2つ(置く、置かない) に減らせる! ©AtCoder Inc. All rights reserved. 113
  114. 114. D問題 • 処理(アルゴリズム) さらに、置くマーブルの順番を決めてしまえば、それ ぞれのマーブルの個数でなく、全てのマーブルの残り 個数の和だけ覚えておけば、次に置くのはどのマーブ ルかを求めることが出来る! • 残りマーブルの状態数が、300 ^ 3から、300 * 3に 削減できる! • これなら制限時間内に解くことが可能となる ©AtCoder Inc. All rights reserved. 114
  115. 115. D問題 処理(アルゴリズム) • 動的計画法の場合 • 適当な2次元配列dpを用意する • dp[今見ている場所][マーブルの残り数] • これに対して、「この状況になるための最小の移動 数」を格納してあげるような、計算の省略を行う。 • マーブルの残り数に対して、移動量の計算が変わる ので注意! ©AtCoder Inc. All rights reserved. 115
  116. 116. D問題 処理(アルゴリズム) • 深さ優先探索を利用したメモ化再帰の場合 • int dfs(今見ている場所,マーブルの残り数)のような再帰 関数を作る。 • 返り値は、その先で全てのマーブルを配置するため に必要な移動数 • こちらもマーブルの残り数から、R,G,Bどのマーブ ルを使うか求める必要があるので注意。 ©AtCoder Inc. All rights reserved. 116
  117. 117. D問題 • 処理(アルゴリズム) 解法3 最小費用流を使おう!(想定外でした。) • Komakiさんの解法からのアイデアです。 • http://abc004.contest.atcoder.jp/submissions/132198 ©AtCoder Inc. All rights reserved. 117
  118. 118. 処理(アルゴリズム) D問題 • こんな感じでグラフを作る • 辺には容量と重みを持たせる (1, -100から箱の距離) (R,0) S (1,0) (1,0) (G,0) T (1,0) (B,0) (1,0) ©AtCoder Inc. All rights reserved. 118
  119. 119. 処理(アルゴリズム) D問題 • こんな感じでグラフを作る • • 辺には容量と重みを持たせる このグラフの最小費用流を求める! (1, -100から箱の距離) (R,0) (1,0) (1,0) (G,0) (1,0) (B,0) (1,0) ©AtCoder Inc. All rights reserved. 119
  120. 120. 処理(アルゴリズム) D問題 • 最小費用流って? • グラフ(丸と矢印で構成されたさっきの図みたいな もの)に関する有名なアルゴリズム • 辺に、「容量」「重み」を持つグラフに対して、始 点から終点までフローを流す。 • 各辺には、辺の容量の分だけフローを流すこと が可能であり、流すごとに重み分のコストがか かる。 • 必要なフローを流すために必要なコストの最小値を 求めるアルゴリズム。 rights reserved. ©AtCoder Inc. All 120
  121. 121. D問題 • 処理(アルゴリズム) 最小費用流の解き方 • グラフを作ったら、ダイクストラで頑張る! • ダイクストラで1つのフローを流し終えたら、逆の 辺を作る。 • フローが流せなくなるまでダイクストラを繰り返 す! • 詳しくはググってね! ©AtCoder Inc. All rights reserved. 121

×