かんプリンの学習記録

勉強したことについてメモしています. 主に競技プログラミングの問題の解説やってます.

JOI2008本選 C - ダーツ

問題はこちら

問題概要

的に{1\le N\le 1000}個の数字が書いてあり, 矢を{4}つまで投げることができる. 矢が当たった数字の和を{1\le M\le 2×10^8}以下での最大値を求めよ.

思考の流れ

個数制限なしナップサック問題っぽいが{1\le M\le 2×10^8}であるので間に合わない.

{\downarrow}

{4}つ投げるっていうのが怪しい. 矢の当たった数字を順に{a,b,c,d}とおくと, {a+b+c+d\le M}になればよい.

{\downarrow}

{a+b\le M-c-d}が成り立つので2つ投げた時にあり得る得点の集合{S}を求める. 同じ数字をえらんでもいいので{a+b}{c+d}が取りうる値の集合はどちらも{S}. {S}の数字を昇順に並べると, {S}のある要素{x}に対して{x\le M-y}となる最大の{S}の要素{y}は二分探索で見つけることができる. {S}のすべての要素{x}に対してこのような{y}を見つけたときの{x+y}の最大値が答えとなる.

提出プログラム

https://atcoder.jp/contests/joi2008ho/submissions/12016002

感想

解法を思い付くのに時間がかかった.