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

第2回 CodeIQプロコン 4問目 ハリセンボンアタック

■■■問題■■■

カメと協力して怪物と戦います。

攻撃手段は、ハリセンボンを捕まえて怪物に投げつけるという方法です。
ただし、ハリセンボンを捕まえるときにあなた・カメ共にいくらかのダメージを受けます。
自分たちが生き残る最低限の体力は残しつつ、怪物にできるだけ大きなダメージを与えてください。

あなた・カメの体力をそれぞれ100と数値化します。
ハリセンボンは何匹かいますが、
怪物に与えるダメージ・あなたが受けるダメージ・カメが受けるダメージは異なっており、
それらはハリセンボン1匹ごとに数値化されたデータセットとして与えられます。

■■■入力■■■

標準入力の1行目に、ハリセンボンの数を表す整数値N(10 <= N <= 50)が与えられます。

2行目以降のN行に、
怪物に与えるダメージ・あなたが受けるダメージ・カメが受けるダメージを表す3つの整数値が
半角スペース区切りで与えられます。

■■■出力■■■

あなた・カメが共に生き残っている(それぞれ体力値が1以上残っている)状態で、
怪物に与えうる最大ダメージを出力してください。


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("10");
            WillReturn.Add("100 10 10");
            WillReturn.Add("120 12 9");
            WillReturn.Add("90 8 9");
            WillReturn.Add("150 16 17");
            WillReturn.Add("145 10 19");
            WillReturn.Add("300 32 27");
            WillReturn.Add("190 15 20");
            WillReturn.Add("170 16 18");
            WillReturn.Add("220 28 15");
            WillReturn.Add("280 31 32");
            //1015
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    struct DamageInfoDef
    {
        internal int Kaibutu;
        internal int Urashima;
        internal int Kame;
    }

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

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

        var DamageInfoList = new List<DamageInfoDef>();
        foreach (string EachStr in InputList.Skip(1)) {
            SplitAct(EachStr);
            DamageInfoDef WillAdd;
            WillAdd.Kaibutu = wkArr[0];
            WillAdd.Urashima = wkArr[1];
            WillAdd.Kame = wkArr[2];
            DamageInfoList.Add(WillAdd);
        }

        //怪物のダメージ[浦島のダメージ,亀のダメージ]なDP表
        int UB = 100 - 1;
        var DP = new Nullable<int>[UB + 1, UB + 1];
        DP[0, 0] = 0;

        int MaxVal = 0;
        foreach (DamageInfoDef EachDamageInfo in DamageInfoList) {
            for (int X = UB; 0 <= X; X--) {
                for (int Y = UB; 0 <= Y; Y--) {
                    if (DP[X, Y] == null) continue;

                    int NewX = X + EachDamageInfo.Urashima;
                    int NewY = Y + EachDamageInfo.Kame;

                    if (UB < NewX || UB < NewY) continue;

                    int NewVal = DP[X, Y].Value + EachDamageInfo.Kaibutu;

                    if (DP[NewX, NewY] == null || DP[NewX, NewY] < NewVal) {
                        DP[NewX, NewY] = NewVal;
                        if (MaxVal < NewVal)
                            MaxVal = NewVal;
                    }
                }
            }
        }
        Console.WriteLine(MaxVal);
    }
}


解説

動的計画法で怪物のダメージ[浦島のダメージ,亀のダメージ]を
順次更新してます。