トップページに戻る    次の競技プログラミングの問題へ    前の競技プログラミングの問題へ

ABC-085-D Katana Thrower

■■■問題■■■

あなたが散歩していると、突然一体の魔物が出現しました。
幸い、あなたは N本の刀、刀1、刀2、・・・、刀N を持っていて、
次の二種類の攻撃を自由な順番で行うことができます。

●持っている刀のうち一本を振る。刀i (1 <= i <= N) を振ると、魔物はaiポイントのダメージを受ける。
  同じ刀を何度振ることもできる。
●持っている刀のうち一本を投げつける。
  刀i (1 <= i <= N) を投げつけると、魔物はbiポイントのダメージを受け、あなたはその刀を失う。
  すなわち、あなたは以後その刀を振ることも投げつけることもできなくなる。

魔物は、受けたダメージの合計がHポイント以上になると消滅します。
魔物を消滅させるには、最小で合計何回の攻撃が必要でしょうか。

■■■入力■■■

N H
a1 b1
・
・
・
aN bN

●1 <= N <= 10万
●1 <= H <= 10億
●1 <= ai <= bi <= 10億
●入力値はすべて整数である

■■■出力■■■

魔物を消滅させるために必要な最小の合計攻撃回数を出力せよ。


C#のソース

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static string InputPattern = "Input1";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("1 10");
            WillReturn.Add("3 5");
            //3
            //あなたは1本の刀を持っていて、
            //振ると3ポイントのダメージ、投げつけると5ポイントのダメージを与えられます。
            //刀を2回振ってから投げつけると 3+3+5=11 ポイントのダメージを与え、
            //合計3回の攻撃で魔物が消滅します。
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("2 10");
            WillReturn.Add("3 5");
            WillReturn.Add("2 6");
            //2
            //先ほどの刀に加えてもう1本別の刀もあり、
            //こちらは振ると2ポイントのダメージ、投げつけると6ポイントのダメージを与えられます。
            //両方の刀を投げつけると 5+6=11 ポイントのダメージを与え、2回の攻撃で魔物が消滅します。
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("4 1000000000");
            WillReturn.Add("1 1");
            WillReturn.Add("1 10000000");
            WillReturn.Add("1 30000000");
            WillReturn.Add("1 99999999");
            //860000004
        }
        else if (InputPattern == "Input4") {
            WillReturn.Add("5 500");
            WillReturn.Add("35 44");
            WillReturn.Add("28 83");
            WillReturn.Add("46 62");
            WillReturn.Add("31 79");
            WillReturn.Add("40 43");
            //9
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    struct ABInfoDef
    {
        internal int A;
        internal int B;
    }

    static void Main()
    {
        List<string> InputList = GetInputList();

        int[] wkArr = { };
        Action<string> SplitAct = pStr =>
            wkArr = pStr.Split(' ').Select(X => int.Parse(X)).ToArray();

        SplitAct(InputList[0]);
        int H = wkArr[1];

        var ABList = new List<ABInfoDef>();
        foreach (string EachStr in InputList.Skip(1)) {
            SplitAct(EachStr);
            ABInfoDef WillAdd;
            WillAdd.A = wkArr[0];
            WillAdd.B = wkArr[1];
            ABList.Add(WillAdd);
        }

        int MaxA = ABList.Max(X => X.A);
        int RestHP = H;
        int Answer = 0;

        foreach (ABInfoDef EachABInfo in ABList.OrderByDescending(X => X.B)) {
            if (EachABInfo.B <= MaxA) break;

            RestHP -= EachABInfo.B;
            Answer++;
            if (RestHP <= 0) break;
        }
        if (RestHP > 0) {
            if (RestHP % MaxA > 0) {
                Answer += RestHP / MaxA + 1;
            }
            else {
                Answer += RestHP / MaxA;
            }
        }
        Console.WriteLine(Answer);
    }
}


解説

刀を振る中での最大ダメージ以上の刀の投げつけを
ダメージの降順に計上してから、
刀を振る中での最大値で割り算してます。