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

AtCoder Beginner Contest 004 解説

Dec 14, 2014

Download

Education

chokudai

AtCoder Beginner Contest 004の解説です。
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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 つのフローを流し終えたら、逆

の辺を作る。

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

す!

• 詳しくはググってね!