見出し画像

[Swift] AtCoder Beginner contest 251(パナソニックプログラミングコンテスト2022)の記録 【A問題・B問題】

概要


・開催日時:2022-05-14(土) 21:00-22:40
・参加前レーティング:12
・参加回数:2回目
・言語:Swift

結果


・A - Six Characters(AC - 100)
・B - At Most 3 (Judge ver.)(WA - (1回))
・コンテスト内順位:5,854位
・参加後レーティング:12→34 (+23)(灰色)

A問題で提出したコード


import Foundation 
 
let S = readLine()!
let count = S.count
var str = ""
 
for i in 0 ..< 6/count {
	str.append(S) 
}
 
print(str)

【ポイント】
・文字列Sを、「文字列Sの文字数÷6で割った回数」が繰り返し上限のforループに入れる
・勝手に6文字の答えが生成される

【感想】
・楽勝でしたね。前回のA問題は7分くらい回答に使ったのですが今回は実質2分30秒くらいで回答することが出来ました。
・反省点としては問題文を読む速さをもっと上げていく必要があると思いました。

【コードレビュー】

今回は特になし

B問題で提出したコード

【自分の回答】

import Foundation 
 
let array = readLine()!.components(separatedBy:" ").map{Int($0)!}
let N = array[0]
let W = array[1]
 
var omoriArray = readLine()!.split(separator: " ").map{ Int($0)! }
omoriArray.sort { $0 < $1 }
var stopperNum = omoriArray.count
var answerArray:Set<Int> = Set<Int>()
 
for i in 0 ..< omoriArray.count {
	if omoriArray[i] >= W {
   		stopperNum = i
        break;
    } else {
    	answerArray.insert(omoriArray[i])
    }
}
 
var ans = 0
 
for k in 0 ..< stopperNum{
  if ans < W - omoriArray[k] {
    ans += omoriArray[k]
    answerArray.insert(ans)
  } else {
    ans = 0
  }
}
 
print(answerArray)

【回答方針】
1. 標準入力を受け取る
2. 重りの配列を降順で並び替える
3.(おもりが一個の場合)Wを超えている重りはそれを選んだ時点でドボンなので、添え字を記憶させる
4. 3で得たストッパーまで配列を回す(計算量を削減するため)
5. 配列内を合計してW以内ならansに格納
6. 重複する値を除外した個数をカウントして表示する

【感想】
・今回もB問題は回答できませんでした。
・敗因は「おもりは3個以下という制約を途中で失念した」ことです。重りの個数=∞の組み合わせをどうすれば実現できるのかってことを90分くらいずっと考えてました。全く見当違いです。
・ただ正解例を見ていたところ、実装方針としてはかなり正解には近づけていたのかなと思います。
・ただそもそも今回は「事前準備の時点でチートシートを違うPCからドライブにアップロードするのを忘れる」「問題文をきちんと読めていない(おもりは3個以下という制約を途中で失念した)」という競プロする以前の問題があったので、そういうケアレスミスは絶対になくしたいです。

【正解例】


https://atcoder.jp/contests/abc251/submissions/31674089

import Foundation
 
let ab = readLine()!.split(separator:" ").map{Int(String($0))!}
let (n, W) = (ab[0], ab[1])
let aa = readLine()!.split(separator:" ").map{Int(String($0))!}
 
var ans: Set<Int> = []
 
// n=1
for i1 in 0..<n {
    if aa[i1] <= W {
        ans.insert(aa[i1])
    }
}
 
// n=2
 
// n=3
if n > 1 {
    for i1 in 0..<(n - 1) {
        for i2 in (i1 + 1)..<n {
            if aa[i1] + aa[i2] <= W {
                ans.insert(aa[i1] + aa[i2])
            }
        }
    }
}
 
// n>3
 
if n > 2 {
    for i1 in 0..<(n - 2) {
        for i2 in (i1 + 1)..<(n - 1) {
            for i3 in (i2 + 1)..<n {
                if aa[i1] + aa[i2] + aa[i3] <= W {
                    ans.insert( aa[i1] + aa[i2] + aa[i3])
                }
            }
        }
    }
}
 
print(ans.count)

・Swiftを使ってACされた方の中でを一番理解しやすかったコードを引用させていただきました。

【解答方針】

・1. 標準入力を受け取る
・2. n=1, n=2, n=3, n<3の場合でケース分けをする
・3. 各重りの個数を合計した値がW以下だったら答え用配列に格納する
・4. 答え用配列の要素数を出力する

個人的によくわからなかったのがforループで+1とかー2とかする処理なんですが、これはforループ内での組み合わせの計算量を削減するためだと理解しています。

サッカーとかで総当たりのリーグ戦をするときの表をイメージすると理解しやすいと思います。

最終的に提出したコード

import Foundation
 
let array = readLine()!.components(separatedBy: " ").map{Int($0)!}
let N = array[0]
let W = array[1]
let omoriArray = readLine()!.components(separatedBy: " ").map{Int($0)!}
var answerArray: Set<Int> = []
 
//n = 1
for i in 0 ..< N {
	if (omoriArray[i] <= W) {
    	answerArray.insert(omoriArray[i])
    }
}
 
//n = 2
if N > 1 {
for i in 0 ..< ( N - 1 ){
    for j in ( i + 1 ) ..< N {
      if omoriArray[i] + omoriArray[j] <= W {
          answerArray.insert(omoriArray[i] + omoriArray[j])
      }
    }
  }
}
 
//n = 3
if N > 2 {
  for i in 0 ..< (N - 2) {
    for j in (i + 1) ..< ( N - 1 ) {
       for k in ( j + 1 ) ..< N {
          if omoriArray[i] + omoriArray[j] + omoriArray[k] <= W {
              answerArray.insert(omoriArray[i] + omoriArray[j] + omoriArray[k])
          }
       }
    }
  }
}
 
 
print(answerArray.count)

・次回は今週土曜日の「AtCoder Beginner Contest 252」に参加させていただきます。よろしくお願いいたします。


いいなと思ったら応援しよう!