AtCoder Beginner Contest 004 解説

121
AtCoder Beginner Contest #004 解解解解 2014 解 2 解 16 解 AtCoder 解解解解 解解解解 ©AtCoder Inc. All rights reserved. 1

description

AtCoder Beginner Contest 004の解説です。

Transcript of AtCoder Beginner Contest 004 解説

Page 1: AtCoder Beginner Contest 004 解説

1

AtCoder Beginner Contest #004

解説資料

2014 年  2 月 16 日AtCoder 株式会社 青木謙尚

©AtCoder Inc. All rights reserved.

Page 2: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 2

目次

1. 競技プログラミングを始める前に

2. A~D 問題

• ところどころに入出力の方法があります

Page 3: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 3

競技プログラミングを始める前に

Page 4: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 4

競技プログラミングを始める前に

(競技)プログラミングを始めたいけど、

そもそもプログラムって何をするの?

Page 5: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 5

競技プログラミングを始める前に

• (競技)プログラミングを始めたいけど、そもそもプ

ログラムって何をするの?

• 大雑把に言うと

1. 情報を受け取って情報 プログラム

Page 6: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 6

• 大雑把に言うと

1. 情報を受け取って

2. 何らかの処理を施して情報を加工する

競技プログラミングを始める前に

• (競技)プログラミングを始めたいけど、そもそもプ

ログラムって何をするの?

情報 プログラム

情報情報 プログラム

Page 7: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 7

競技プログラミングを始める前に

• (競技)プログラミングを始めたいけど、そもそもプ

ログラムって何をするの?

• 大雑把に言うと

1. 情報を受け取って

2. 何らかの処理を施して情報を加工する

3. そしてどこかへ渡す

情報情報 プログラム

情報 プログラム

情報情報 プログラム

Page 8: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 8

競技プログラミングを始める前に

• 具体例

検索

くおえうえーーーるえうおおお 可愛い

Page 9: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 9

競技プログラミングを始める前に

• 具体例

検索

くおえうえーーーるえうおおお 可愛い

Gaagle受け取る

Page 10: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 10

競技プログラミングを始める前に

• 具体例

検索

くおえうえーーーるえうおおお 可愛い

Gaagle受け取る

検索という処理

検索結果

Page 11: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 11

競技プログラミングを始める前に

• 具体例

検索

くおえうえーーーるえうおおお 可愛い

Gaagle受け取る

検索結果

検索という処理

結果を渡す

Page 12: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 12

競技プログラミングを始める前に

• 入出力ができなければ、

• “ くおえうえーーーるえうおおお 可

愛い”

• を受け取れないし、

• 検索結果も渡せない

Page 13: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 13

競技プログラミングを始める前に

• 入出力ができなければ、

• “ くおえうえーーーるえうおおお 可

愛い”

• を受け取れないし、

• 検索結果も渡せない

• アルゴリズムより先にすることがある!

• 本当に本当に始めたばかりの人へ

• まずは入出力から始めませんか?

Page 14: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 14

A 問題

1. 問題概要

2. 入力

3. 処理(アルゴリズム)

4. 出力

Page 15: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 15

1. 整数 N が与えられる。

2. 2*N を出力せよ。

A 問題 問題概要

Page 16: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 16

A 問題 問題概要

1. 整数 N が与えられる。

入力される値である N を保存する!

2. 2*N を出力せよ。

保存した N に 2 をかけて出力する!

Page 17: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 17

A 問題 入力

• 入力の取り方は標準入出力でググってください• とはいえ、少しだけサンプルを載せます• コードの色は• 受け取り• 処理• 出力

• を表したものではないので、注意して下さい• AtCoder へ提出したときの色です

Page 18: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 18

• C

#include<stdio.h>int main(){ int N; scanf("%d", &N); return 0;}

A 問題 入力

Page 19: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 19

• C++

#include<iostream>int main(){ int N; std::cin >> N; return 0;}

A 問題 入力

Page 20: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 20

• Java

import java.util.Scanner;public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); }}

A 問題 入力

Page 21: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 21

• C#

using System;class Program{ static void Main(string[] args){ int N = int.Parse(Console.ReadLine()); }}

A 問題 入力

Page 22: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 22

• その他

• http://practice.contest.atcoder.jp/ を参照してください

• たいていの言語の例があります

A 問題 入力

Page 23: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 23

• さきほどから入力を受け取ると何度も書いてま

すが、受け取るためには保存するための入れ物

が必要です。

A 問題 補足(変数と型について)

• プログラムの世界でも入れ物に形があります。

これを型といいます。

Page 24: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 24

• 型の例

整数型 int

0, 1, 2 … 100 … などの整数

文字型 char

a, b, c … A, B … などの 1 文字

• 各型で表現できる最大、最小の値は言語や処

理系で変化します

A 問題 補足(変数と型について)

Page 25: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 25

• 変数について

              とすると、

さらに              とする

A 問題 補足(変数と型について)

int variable = 4;

variable という入れ物に 4 が入りますvariable

4

variable = 1;

variable に 1 が上書きされますvariable

1

Page 26: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 26

受け取った N に

2 をかける

A 問題 処理(アルゴリズム)

Page 27: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 27

受け取った N に

2 をかける

コードは以下だけ

A 問題 処理(アルゴリズム)

N = N * 2;

Page 28: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 28

処理の結果を出力します

A 問題 出力

• C

printf(“%d\n”, N);

• C++

cout << N << endl;

Page 29: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 29

A 問題 出力

• Java

System.out.println(N);

• C#

Console.WriteLine(N);

Page 30: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 30

B 問題

1. 問題概要

2. 入力

3. 処理(アルゴリズム)

4. 出力

Page 31: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 31

1. 4x4 の盤面が与えられる。

2. 盤面を 180 度回転させて出力せよ。

B 問題 問題概要

Page 32: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 32

1. 4x4 の盤面が与えられる。

盤面を保存する

2. 盤面を 180 度回転させて出力せよ。

盤面を 180 度回転させる

出力する

B 問題 問題概要

Page 33: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 33

B 問題 問題概要

絶望ポイントその1• 盤面の状態ってどう保存すればいいん

だ!?

絶望ポイントその2• 180 度の回転ってどうやればいいんだ!?

Page 34: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 34

B 問題 問題概要

絶望ポイントその1• 盤面の状態ってどう保存すればいいん

だ!? 配列を使いましょう

絶望ポイントその2• 180 度の回転ってどうやればいいんだ!? コピー用の配列を作る 元の配列を逆からコピーする

Page 35: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 35

B 問題 入力

まずは盤面の保存から• 配列って何?

Page 36: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 36

B 問題 入力

まずは盤面の保存から• 配列って何?

連続した箱です

• 世界で最も偉大な箱かも

Page 37: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 37

B 問題 入力

まずは盤面の保存から• 配列って何?

1 つだけだと変数

連続してたら配列

Page 38: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 38

B 問題 入力

まずは盤面の保存から• どこが偉大なの?

縦に並べることができる これで盤面が作れる!

Page 39: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 39

B 問題 入力

まずは盤面の保存から• 配列の概念はわかったけど、何をすればい

いの?

Page 40: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 40

B 問題 入力

まずは盤面の保存から• 配列の概念はわかったけど、何をすればい

いの?

宣言して下さい

Page 41: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 41

B 問題 入力

2 次元配列の宣言

• C/C++

char board[4][4];

• Java

char[][] board = new char[4][4];

• C#

char[,] board = new[4, 4];

Page 42: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 42

B 問題 補足(配列のアクセス方法)

array という配列を宣言する

すでに文字が格納されているとするa # z %

array[0]array[1]

array[2]array[3]

array[0] のようにしてアクセスできる

0 から始まることに注意!

1

2

3

char array [4];

a # z %

Page 43: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 43

B 問題 補足(配列のアクセス方法2)

board という 2 次元配列を宣言する

char board[2][2];

board

board

a #

z %同様に、何らかの文字が入っているとする

board[1][0]

a #

z % board[1][1]

board[0][0] board[0][1]board[0][0] には ’ a’board[0][1] には ’ #’board[1][0] には ’ z’board[1][1] には ’ %’

Page 44: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 44

B 問題 処理(アルゴリズム)

180 度の回転ってどうするの?

コピー用の配列を用意します。

          を宣言しておきます。

元の配列を逆からコピー用の配列に移します。

for 文を使います。

char copy[4][4];

Page 45: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 45

B 問題 処理(アルゴリズム)

コーディングに入る前に、いまからすることを図示します。1. コピー用の配列を宣言します。

char copy[4][4];

Page 46: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 46

B 問題 処理(アルゴリズム)

O x x

x x

x x

x x

x x

x x xx

x

x

2. 元の配列を逆からコピー用の配列に移します。

board copy

Page 47: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 47

B 問題 処理(アルゴリズム)

O x x

x x

x x

x x

x x

x x xx

x

x x

board copy

2. 元の配列を逆からコピー用の配列に移します。

Page 48: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 48

B 問題 処理(アルゴリズム)

O x x

x x

x x

x x

x x

x x xx

x

x x x

board copy

2. 元の配列を逆からコピー用の配列に移します。

Page 49: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 49

B 問題 処理(アルゴリズム)

途中を省略して…

Page 50: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 50

B 問題 処理(アルゴリズム)

O x x

x x

x x

x x

x x

x x xx

x

xx

xx

xx

xx

xx

xxx x

x

board copy

2. 元の配列を逆からコピー用の配列に移します。

Page 51: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 51

B 問題 処理(アルゴリズム)

O x x

x x

x x

x x

x x

x x xx

x

xx

xx

xx

xx

xx

xxx x

x O

board copy

2. 元の配列を逆からコピー用の配列に移します。

Page 52: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 52

B 問題 処理(アルゴリズム)

• 移せばよいことはわかったけど、実際にどうするの?

for 文を使います。

for 文とは繰り返し行われる処理を記述するもので

す。• 復習

2 次元配列の添字について

Page 53: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 53

B 問題 処理(アルゴリズム)

[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]

• 2 次元配列の添字について

• 注意点

数学の xy 座標と

は異なる

マスは 4x4 だが、

添字は [3,3] まで

Page 54: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 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]; }}

Page 55: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 55

B 問題 処理(アルゴリズム)

• for 文のコード (i = 0, j = 0 のと

き )

O x x

x x

x x

x x

x x

x x xx

x

x

board copy

copy[0][0] = board[3-0][3-0];

Page 56: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 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 xx

xx x

board copy

Page 57: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 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 xx

xx x x

board copy

Page 58: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 58

B 問題 処理(アルゴリズム)

途中を省略して…

Page 59: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 59

B 問題 処理(アルゴリズム)

• for 文のコード (i = 3, j = 2 のと

き ) copy[3][2] = board[3-3][3-2];

O x x

x x

x x

x x

x x

x x xx

x

xx

xx

xx

xx

xx

xxx x

x

board copy

Page 60: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 60

B 問題 処理(アルゴリズム)

• for 文のコード (i = 3, j = 3 のと

き ) copy[3][3] = board[3-3][3-3];

O x x

x x

x x

x x

x x

x x xx

x

xx

xx

xx

xx

xx

xxx x

x O

board copy

Page 61: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 61

xx

xx

xx

xx

xx

xxx x

x O

x

B 問題 出力

3.180 度回転させたものを順に出力するだけ これも for を使って書いて下さい。

copy

Page 62: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 62

B 問題 処理(アルゴリズム)

途中を省略して…

Page 63: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 63

xx

xx

xx

xx

xx

xxx x

x O

x

B 問題 出力

3.180 度回転させたものを順に出力するだけ

x

xx

xx

xx

xx

xx

xx

x O

copy

Page 64: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 64

C 問題

1. 問題概要

2. 処理(アルゴリズム)

Page 65: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 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} 番目のカードを入れ

替える。

Page 66: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 66

C 問題 補足(剰余について)

• 剰余演算子 % について

要は「余り」のこと

7%3 は「 7 を 3 で割った余り」を意味す

つまり 1

ほとんどのプログラミング言語では % が剰

余演算子として実装されている

Page 67: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 67

C 問題 処理(アルゴリズム)

1. この問題のポイントは、 N の値に大きな値が

含まれること ( 最大で N=10^9 まで )

2. つまり、普通に交換していくだけでは時間的な

制約上、満点を得るのは厳しい (2s 以内 )

3. ここに気づくことができるかが、満点を得るた

めのポイント

できるだけ交換回数を減らしたい!

Page 68: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 68

C 問題 処理(アルゴリズム)

• とはいえ、まずは実験してみる

1 2 3 4 5 6初期状態

2 1 3 4 5 6i = 0

2 3 1 4 5 6i = 1

Page 69: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 69

C 問題 処理(アルゴリズム)

• まずは実験してみる

2 3 4 1 5 6i = 2

2 3 4 5 1 6i = 3

2 3 4 5 6 1i = 4

Page 70: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 70

C 問題 処理(アルゴリズム)

• あれ? 1 が右端に移動して 2~6 までは整列している・・・ ?

2 3 4 5 6 1i = 4

• さらに実験してみる

3 2 4 5 6 1i = 5

Page 71: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 71

C 問題 処理(アルゴリズム)

• さらに実験してみる

3 4 2 5 6 1i = 6

3 4 5 2 6 1i = 7

3 4 5 6 2 1i = 8

Page 72: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 72

C 問題 処理(アルゴリズム)

• 先頭から 3~6 が整列している。で、後ろに 1 と 2 が並んでいる。

• ということは、もっと進めてみると以下のようになるのでは?

4 5 6 1 2 3i = ?

3 4 5 6 1 2i = 9

Page 73: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 73

C 問題 処理(アルゴリズム)

• さらにさらに進めると、きっとこういった遷移が行われるはず

5 6 1 2 3 4i = ??

6 1 2 3 4 5i = ???

1 2 3 4 5 6i = ????

Page 74: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 74

C 問題 処理(アルゴリズム)

• i がいくつのときかはわからないけれど、初期状態に帰ってく

る?

あくまでも現段階では予想である

1 2 3 4 5 6i = ????

1 2 3 4 5 6i = 0

Page 75: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 75

C 問題 処理(アルゴリズム)

• 確かめてみる!

方法は、カードの遷移を出力する

i = 0   213456i = 1   231456i = 2   234156

i = 29   123456i = 30   213456

:発見!

Page 76: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 76

C 問題 処理(アルゴリズム)

• 確かめてみる!

方法は、カードの遷移を出力する

i = 0   213456i = 1   231456i = 2   234156

i = 29   123456i = 30   213456

:交換回数は i が0 から 29 までの 30 回

カードが 6 枚あって、入れ替え可能な場所が 5 通りあるから6 x 5 = 30 回交換すると初期状態に戻る

Page 77: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 77

C 問題 処理(アルゴリズム)

• 実験の結果、 30 回交換すると初期状態に戻ることが

わかった。

31 回の交換は、 1 回の交換と同じ。

32 回の交換は、 2 回の交換と同じ。

100 回の交換は?

100 mod 30 => 10 より、 10 回の交換と同

30 で割ったときの余り(剰余)がポイント

• N を 30 で割ったときの余りで交換すればよい

Page 78: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 78

C 問題 処理(アルゴリズム)

• これで N の値が大きくなっても対応できる!

たとえば、 N = 1000 のとき、実際に 1000 回交

換するのではなく、 1000 mod 30 => 10 回交換

すればよい

30 で割ったときの余りは、 0~29 の 30 通りある

が、

最大でも 29 回ですむ。N = N % 30;

としておけばよい

Page 79: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 79

C 問題 処理(アルゴリズム)

• 数値の入れ替えの仕方

• A, B を入れ替えたい時の処理

• C = A;

• A = B;

• B = C;

• のように、 C を中継してあげれば入れ替えることが出

来る。

• C++ などは、標準で swap関数が用意されている

Page 80: AtCoder Beginner Contest 004 解説

80

AtCoder Beginner Contest #004

解説資料 続き

2014 年  2 月 16 日AtCoder 株式会社 高橋直大

©AtCoder Inc. All rights reserved.

Page 81: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 81

D 問題

1. 問題概要

2. 処理(アルゴリズム)

Page 82: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 82

D 問題 問題概要

• 番号がついた箱が無限個並んでおり、左から順番

に、 ..,-2,-1,0,1,2,.. と番号がついている

• いくつかの箱には、マーブルが入っている。

• 番号 -100 の箱には、赤いマーブルが R個

• 番号 0 の箱には、緑のマーブルが G個

• 番号 100 の箱には、青いマーブルが B個

• これらのマーブルを、1個隣の箱に移動することが出

来る。

• 全ての箱に、マーブルが2個以上入っていない状態に

する。

• 移動回数の最小値を求めよ。

Page 83: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 83

D 問題 問題概要 

• 部分点1

• R, G, B ≦ 5

• 部分点2

• R, G, B ≦ 40

• 満点

• R, G, B ≦ 300

Page 84: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 84

D 問題 処理(アルゴリズム) 

• 例えば、 G が 4 の時

-3 -2 -1 0 1 2 3

Page 85: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 85

D 問題 処理(アルゴリズム) 

• 例えば、 G が 4 の時

• マーブルを右に

-3 -2 -1 0 1 2 3

Page 86: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 86

D 問題 処理(アルゴリズム) 

• 例えば、 G が 4 の時

• マーブルを右に2回移動して

-3 -2 -1 0 1 2 3

Page 87: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 87

D 問題 処理(アルゴリズム) 

• 例えば、 G が 4 の時

• マーブルを右に2回移動して、さらにもう1個右に

-3 -2 -1 0 1 2 3

Page 88: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 88

D 問題 処理(アルゴリズム) 

• 例えば、 G が 4 の時

• マーブルを右に2回移動して、さらにもう1個右に

• 最後に左に移動しておしまい

-3 -2 -1 0 1 2 3

Page 89: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 89

D 問題 処理(アルゴリズム) 

• 部分点 1 は、このように、 R,G,B に対して、左右に

マーブルを振り分けてあげれば良い。

• 深さ優先探索や、幅優先探索を使っても OK 。

• 部分点 2 も、右、左、右、左、と振り分けてあげてし

まえば、 R,G,B のマーブルが 40個以下、かつ、箱の

数が 100個離れているので、重なることもなく、解く

ことが出来る。

• 満点解法は、もう少し考察が必要。

Page 90: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 90

D 問題 処理(アルゴリズム)

• どのマーブルを右に、どのマーブルを左に・・・と考

えるのは非常に面倒!

• 最後の状態だけ考えて、そこから、その状態にするの

に必要な手数を考えたい。

3 2 1 0 1 2 3 3 2 1 0 1 2 3

Page 91: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 91

D 問題 処理(アルゴリズム)

• どのマーブルを右に、どのマーブルを左に・・・と考

えるのは非常に面倒!

• 最後の状態だけ考えて、そこから、その状態にするの

に必要な手数を考えたい。

• 単純に、移動距離を足し算してあげればOK!

3 2 1 0 1 2 3 3 2 1 0 1 2 3

1+1+2=4

1 1 2

Page 92: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 92

D 問題 処理(アルゴリズム)

• R,G,B が大きくなると・・・

… …

: :

Page 93: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 93

D 問題 処理(アルゴリズム)

• R,G,B が大きくなると・・・

• 同じ広げ方をすると、被ってしまうことがある!

• 単純に右、左、右、左、と考えるだけではダメ。

… …

Page 94: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 94

D 問題 処理(アルゴリズム)

• 解法 1  広げ方の全探索!

• 図のように、途中で間が空くことはありえない。

• よって、赤・緑・青のマーブルの入っている、一番左

の箱だけ決めれば、最終状態は確定する。

• これだけだと、それぞれ可能性のある場所が 1000

近くあるため、微妙に間に合わない。

• 高速な実装をすればこれでもギリギリ間に合う。

3 2 1 0 1 2 3

Page 95: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 95

D 問題 処理(アルゴリズム)

• 赤、緑、青に対して、それぞれ全て全探索をすると、

計算量が 3乗になってしまい間に合わない。

• 何か工夫が必要

• 緑から先に決めてあげることによって、赤と青を別々

に計算することが出来る!

Page 96: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 96

D 問題 処理(アルゴリズム)

• 例えば図のような場合

Page 97: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 97

D 問題 処理(アルゴリズム)

• 例えば図のような場合

• まず緑の広げ方を決めてあげる

Page 98: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 98

D 問題 処理(アルゴリズム)

• 例えば図のような場合

• まず緑の広げ方を決めてあげる

• すると、赤の広げ方、青の広げ方は、それぞれの広げ

方に干渉しない。

• よって、 2乗の計算量で計算することが可能になる!

Page 99: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 99

D 問題 処理(アルゴリズム)

• 広げる時のコストは、 O(1) の計算量で計算すること

が可能。

• それぞれのマーブルの移動距離は、中央で区切ると

等差数列になるため、足し算が可能。

• 3,2,1,0,1,2,3,4,5,6みたいな配列になる。

Page 100: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 100

D 問題 処理(アルゴリズム)

• そもそも、部分点2と同じ並べ方をまず試してみて、

それが収まるなら、探索する必要はない。

Page 101: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 101

D 問題 処理(アルゴリズム)

• そもそも、部分点2と同じ並べ方をまず試してみて、

それが収まるなら、その解を採用すれば良いので、探

索する必要はない。

• 収まらないなら、限界まで中央に寄せてあげれば良い

ので、こちらも探索する必要はない。

Page 102: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 102

D 問題 処理(アルゴリズム)

• 緑が中心だとダメな例!

• 緑・赤が多くて、青が少ない場合。

Page 103: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 103

D 問題 処理(アルゴリズム)

• 緑が中心だとダメな例!

• 緑・赤が多くて、青が少ない場合。

• 赤を跳ね飛ばすと、赤を大量に移動させないといけな

くなってしまう。

Page 104: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 104

D 問題 処理(アルゴリズム)

• 緑が中心だとダメな例!

• 緑・赤が多くて、青が少ない場合。

• 赤を跳ね飛ばすと、赤を大量に移動させないといけな

くなってしまう。→緑を右に移動してあげないといけ

ない!

Page 105: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 105

D 問題 処理(アルゴリズム)

• 解法2 動的計画法を使おう!

• 左の箱から順番に、「赤を置く」「緑を置く」「青を

置く」「置かない」の 4 通りの全探索が考えられる。

• 範囲は適当に -1000 から +1000 の箱までやるとして、

2000 回程度の分岐

• このまま全探索すると、 4^2000程度の計算量

• これを、動的計画法 orメモ化再帰をしてあげるこ

とにより、解いてあげる。

Page 106: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 106

D 問題 処理(アルゴリズム)

• まず、一番左に対して4つの分岐

Page 107: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 107

D 問題 処理(アルゴリズム)

• まず、一番左に対して4つの分岐

Page 108: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 108

D 問題 処理(アルゴリズム)

• 動的計画法・メモ化再帰とは?

• 一度計算したものを、二度計算しなかったり、同じも

のを纏めて計算してあげることにより、計算量を大幅

に削減してあげるテクニック

Page 109: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 109

D 問題 処理(アルゴリズム)

• 今回の場合は、左から順番に探索してあげるとして、

• どの箱を見ているか

• 赤いマーブルがいくつ残っているか

• 緑のマーブルがいくつ残っているか

• 青のマーブルがいくつ残っているか

• しか状態が存在しない。

Page 110: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 110

D 問題 処理(アルゴリズム)

• 動的計画法の場合

• 適当な4次元配列 dp を用意する

• dp[今見ている場所 ][赤の残り数 ][緑の残り数 ][ 青の

残り数 ]

• これに対して、「この状況になるための最小の移動

数」を格納してあげるような、計算の省略を行う。

Page 111: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 111

D 問題 処理(アルゴリズム)

• 深さ優先探索を利用したメモ化再帰の場合

• int dfs(今見ている場所 ,赤の残り数 ,緑の残り数 , 青

の残り数 ) のような再帰関数を作る。

• 返り値は、その先で全てのマーブルを配置するため

に必要な移動数

Page 112: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 112

D 問題 処理(アルゴリズム)

• このように動的計画法・メモ化再帰を行うと、それぞ

れの状態数は、 2000 * 300 * 300 * 300程度存在し、

それぞれに対して分岐の数が 4 つ。

• これでは計算量が大きすぎる!

• もう少し工夫をしてあげる必要がある。

Page 113: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 113

D 問題 処理(アルゴリズム)

• 考察をすることで、計算量を削減しよう!

• 先ほどは、「赤を置く」「緑を置く」「青を置く」

の 3 通りの置き方を考慮していた。

• しかし、左から順番に、赤・緑・青と並ぶのが自然

であり、赤が置けるなら緑・青を置く必要はないし、

緑が置けるなら青を置く必要はない。(今回の問題

設定では出来ない!)

• つまり、分岐の数を 4 つから 2 つ(置く、置かな

い)に減らせる!

Page 114: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 114

D 問題 処理(アルゴリズム)

• さらに、置くマーブルの順番を決めてしまえば、それ

ぞれのマーブルの個数でなく、全てのマーブルの残り

個数の和だけ覚えておけば、次に置くのはどのマーブ

ルかを求めることが出来る!

• 残りマーブルの状態数が、 300 ^ 3 から、 300 *

3 に削減できる!

• これなら制限時間内に解くことが可能となる

Page 115: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 115

D 問題 処理(アルゴリズム)

• 動的計画法の場合

• 適当な 2 次元配列 dp を用意する

• dp[今見ている場所 ][ マーブルの残り数 ]

• これに対して、「この状況になるための最小の移動

数」を格納してあげるような、計算の省略を行う。

• マーブルの残り数に対して、移動量の計算が変わる

ので注意!

Page 116: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 116

D 問題 処理(アルゴリズム)

• 深さ優先探索を利用したメモ化再帰の場合

• int dfs(今見ている場所 , マーブルの残り数 ) のような

再帰関数を作る。

• 返り値は、その先で全てのマーブルを配置するため

に必要な移動数

• こちらもマーブルの残り数から、 R,G,B どのマー

ブルを使うか求める必要があるので注意。

Page 117: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 117

D 問題 処理(アルゴリズム)

• 解法3 最小費用流を使おう!(想定外でした。)

• Komaki さんの解法からのアイデアです。

• http://

abc004.contest.atcoder.jp/submissions/13219

8

Page 118: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 118

D 問題 処理(アルゴリズム)

• こんな感じでグラフを作る

• 辺には容量と重みを持たせる

S T

(1, -100 から箱の距離 )

(1,0)(1,0)

(1,0)

(1,0)

(R,0)

(G,0)

(B,0)

Page 119: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 119

D 問題 処理(アルゴリズム)

• こんな感じでグラフを作る

• 辺には容量と重みを持たせる

• このグラフの最小費用流を求める!

(1, -100 から箱の距離 )

(1,0)(1,0)

(1,0)

(1,0)

(R,0)

(G,0)

(B,0)

Page 120: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 120

D 問題 処理(アルゴリズム)

• 最小費用流って?

• グラフ(丸と矢印で構成されたさっきの図みたい

なもの)に関する有名なアルゴリズム

• 辺に、「容量」「重み」を持つグラフに対して、始

点から終点までフローを流す。

• 各辺には、辺の容量の分だけフローを流すこと

が可能であり、流すごとに重み分のコストがか

かる。

• 必要なフローを流すために必要なコストの最小値を

求めるアルゴリズム。

Page 121: AtCoder Beginner Contest 004 解説

©AtCoder Inc. All rights reserved. 121

D 問題 処理(アルゴリズム)

• 最小費用流の解き方

• グラフを作ったら、ダイクストラで頑張る!

• ダイクストラで 1 つのフローを流し終えたら、逆

の辺を作る。

• フローが流せなくなるまでダイクストラを繰り返

す!

• 詳しくはググってね!