Upload
yuma-inoue
View
785
Download
0
Embed Size (px)
Citation preview
B. 超大型連休
法改正によって、祝日が特定の n 日に変更になる2012 年における最大連休は何日間か求めよただし、休日は土・日・祝日および振替休日とする祝日が既に休日のとき、振替休日を設ける振替休日は祝日の時系列順に決定していき、その祝日
以降最も近い平日 ( 祝日や振替休日は平日でない ) となる
また、 2012 年 1 月 1 日は日曜日である各月毎の日数は以下の表を参考にせよ
問題概要
月 1 2 3 4 5 6 7 8 9 10 11 12
日数 31 29 31 30 31 30 31 31 30 31 30 31
Input n / / … /
n : 祝日の日数 (0≦n≦366) : i 番目に与えられる祝日の月 (1≦ ≦12) : i 番目に与えられる祝日の日 (=2: 1≦≦31, =4,6,9,11: 1≦≦30, それ以外 : 1≦≦31) すべて整数、月と日は” /” で区切られている 祝日は時系列順に与えられるとは限らない 同じ日付は複数回与えられることはない
Output 最大の連休の日数を整数一行で出力
入出力形式・制約
Sample Input11/9
Sample Output3
1/7( 土 ),1/8( 日 ),1/9( 月・祝 ) の 3 連休が最長である
例 1
1
8
2
9
310
411
512
613
714
土日 月 火 水 木 金
Sample Input11/10
Sample Output2
1/7( 土 ),1/8( 日 ) などの二連休が最長である
例 2
1
8
2
9
310
411
512
613
714
土日 月 火 水 木 金
Sample Input11/7
Sample Output3
1/7 は土曜日のため、最も近い平日である 1/9 が振替休日となるよって、 1/7( 土 ),1/8( 日 ),1/9( 月 ) の 3 連休が最長である
例 3
1
8
2
9
310
411
512
613
714
土日 月 火 水 木 金
Sample Input21/71/9
Sample Output4
1/7 は土曜日のため、最も近い平日である 1/10 が振替休日となる1/9 は祝日であるよって、 1/7( 土 ),1/8( 日 ),1/9( 月 ),1/10( 火 ) の 4 連休が最長で
ある
例 4
1
8
2
9
310
411
512
613
714
土日 月 火 水 木 金
プロコンガチ勢には耳タコな内容なので読み飛ばしてください
日付問題は数学的に解けるものもあるが、シミュレーションが楽 month = 1; day = 1; から始める day++ すると1日進む day がその月の日数を超えたら day = 1; month++; すると次の月
になる その月の日数は配列で覚えておくとよい int num_month[] = {31,29,31,30, … ,30,31} とか
曜日は、最初の曜日と、 ( 最初の日から経過した日数 )mod7 でわかる 最初の日が日曜日のとき、 mod7 = 0 なら日曜、 mod7 = 1 なら月
曜 最初の日から経過した日数は、カウンタを用意して日が進む毎に ++
日付問題の解き方
よくある日付問題と同じく、日をずらしていくタイムドリブン 12×31 の bool 配列に、休日かどうかをメモしていく 祝日チェックは 12×31 の bool 配列などを別に作ると楽
一回目のループ 土日の場合は休日フラグ true 土日でなく、かつ祝日なら休日フラグを true にしつつ祝日フラグ
false 土日でも祝日でもない場合は休日フラグ false
二回目のループ 祝日フラグが立っているものについて、日を進めていって初めて休日
フラグが false のところを true にして、祝日フラグ false三回目のループ
true が連続している数の最大値を求める二回目のループで二重ループが入るので、 O(366×n) くらい
想定解法
よく考えると、先に土日でない祝日を確定しておく必要はない 祝日になる予定の日が先に他の祝日の振替休日になっても、そのまま振
替休日を求めれば休日になる日は全体で変わらない
よって、貪欲に振替休日を求めてもよい ( ループ 1 はいらない )さらに、祝日残数カウンタ (syuku とおく ) を作ると O(366)
現在の連休数を seq とおく 現在の日付が祝日なら syuku++ その後、
現在の日付が土日なら、 syuku はいじらず seq++ 現在の日付が土日でない、かつ syuku>0 なら、 seq++,syuku— 現在の日付が土日でない、かつ syuku==0 なら、 ans = max(ans,seq),
seq = 0
想定解法 2
祝日 A 祝日 B
振替 A
祝日 B
振替 B
振替 A
土 日 月 火
休日的には同じ
先に固定→貪欲決定→
ちゃんと読まずに閏年で 2/29 があるのを忘れる
振替休日が上手くいかない 連続する土日の両方とも祝日の場合 振替休日が祝日の場合
“2012 年の連休数”なのに 2013 年に突入してしまう 数学的に理論値とかを出そうとすると起こりそう 境界条件ミス (12/31 、 366 日でストップ ) 12/31 を過ぎる振替休日がある場合に連休に入れてしまう
12/31 でループが終わった後にも ans = max(ans,seq) しなければいけないのを忘れる
祝日の日付が時系列順に与えられるとは限らないのを忘れる
祝日が 0 日のとき
“/” 区切り処理に手間取る (C なら scanf(“%d/%d”,&m,&d) で OK)
やらかすかもしれないところ
某人が「 AtCoder は日付問題が多い」と言っていたのに最近出てなかったようなのでつい
“ 重めの実装すればだいたいの人が通せるけど、賢くやると実装が軽くなる”みたいな問題は教育的な位置づけとなり得るB問題としてよいのではないか ( 個人的な見解 )
元ネタ