1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HaskellでABC431を解く

Last updated at Posted at 2025-11-08

はじめに

ABC431に参加しました。

A問題

頭と体の重さを比較します。

main = do
  [h,b] <- readInts
  if b >= h then
    print 0
  else
    print (h-b)

A問題提出

B問題

現在どのパーツがくっついているかをIntMapで管理しつつ全体の重さを管理します。パーツの総数が100なので重さを参照する際はリストにインデクスアクセスしている。Nが大きくなるとArrayやVectorにしないとTLEしてしまうのでそちらを使ったほうが安心です。

main = do
  x <- readLn :: IO Int
  n <- readLn :: IO Int
  ws <- readInts
  q <- readLn :: IO Int
  ps <- replicateM q readLn :: IO [Int]
  putStr $ unlines $ map show $ solve IS.empty x ws ps

solve im w ws [] = []
solve im w ws (p:ps)
  | IS.member p im = wSub : solve (IS.delete p im) wSub ws ps
  | otherwise = wAdd : solve (IS.insert p im) wAdd ws ps
  where
    wSub = w - ws !! (p-1)
    wAdd = w + ws !! (p-1)

B問題提出

C問題

頭パーツと体パーツをソートしておいてできるだけ小さい頭と小さい体を使うようにする。
体パーツが頭パーツよりも小さい場合はスルーしてトータルでK体ロボットが作れるかを判定する。

main = do
  [n,m,k] <- readInts
  hs <- sort <$> readInts
  bs <- sort <$> readInts
  let cands = solve hs bs
  if length cands >= k then
    putStrLn "Yes"
  else
    putStrLn "No"

solve [] _ = []
solve _ [] = []
solve hhs@(h:hs) bbs@(b:bs)
  | h <= b = (h,b) : solve hs bs
  | otherwise = solve hhs bs

C問題提出

D問題

最初DPぽいなと思いつつ遷移表がかけなかったので安易とは思いつつ
「2^Nの組み合わせを使って頭の重さが半分を超えた場合に枝かりをする」という方針で取り組んだところやはりTLE。。。
終了間際にDPに戻ってコンテスト終了20分後にDPで解けました。

main = do
  n <- readLn :: IO Int
  whbs <- replicateM n $ do
    [w,h,b] <- readInts
    return (w,h,b)
  let wSum = sum $ map (\(w,h,b) -> w) whbs
  let wSum_2 = wSum `div` 2
  print $ maximum $ solve n wSum_2 whbs

solve :: Int -> Int -> [(Int,Int,Int)] -> [Int] -- A.UArray (Int,Int) Int
solve n wSum_2 whbs = runST $ do
  arr <- AM.newArray ((0,0),(n,wSum_2)) (minBound::Int) :: ST s (STUArray s (Int,Int) Int) -- 型に注意
  AM.writeArray arr (0,0) 0 -- DPテーブルの初期値設定
  forM_ [0..n-1] $ \i -> do
    let (w,h,b) = whbs !! i
    forM_ [0..wSum_2] $ \j -> do
      val0 <- AM.readArray arr (i,j)
      when (val0 /= (minBound::Int)) $ do
        when ( j+w <= wSum_2 ) $ do
          val1 <- AM.readArray arr (i+1,j+w)
          AM.writeArray arr (i+1,j+w) $ max val1 (val0 + h)
        when ( j <= wSum_2 ) $ do
          val1 <- AM.readArray arr (i+1,j)
          AM.writeArray arr (i+1,j) $ max val1 (val0 + b)
  forM [0..wSum_2] $ \j -> do
    val <- AM.readArray arr (n,j)
    return val

D問題提出

おわりに

D問題がDPっぽいなと思ったにもかかわらずTLEなる方針を立ててしまったところが敗因です。もうちょっとDP方向で詰めて考えればよかったです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?