AOJ本の読書メモ   AOJ    次のAOJの問題へ    前のAOJの問題へ

AOJ 1187 ICPCの順位付け


問題へのリンク


C#のソース

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

class Program
{
    static string InputPattern = "InputX";

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

        if (InputPattern == "Input1") {
            WillReturn.Add("300 10 8 5");
            WillReturn.Add("50 5 2 1");
            WillReturn.Add("70 5 2 0");
            WillReturn.Add("75 1 1 0");
            WillReturn.Add("100 3 1 0");
            WillReturn.Add("150 3 2 0");
            WillReturn.Add("240 5 5 7");
            WillReturn.Add("50 1 1 0");
            WillReturn.Add("60 2 2 0");
            WillReturn.Add("70 2 3 0");
            WillReturn.Add("90 1 3 0");
            WillReturn.Add("120 3 5 0");
            WillReturn.Add("140 4 1 0");
            WillReturn.Add("150 2 4 1");
            WillReturn.Add("180 3 5 4");
            WillReturn.Add("15 2 2 1");
            WillReturn.Add("20 2 2 1");
            WillReturn.Add("25 2 2 0");
            WillReturn.Add("60 1 1 0");
            WillReturn.Add("120 5 5 4");
            WillReturn.Add("15 5 4 1");
            WillReturn.Add("20 5 4 0");
            WillReturn.Add("40 1 1 0");
            WillReturn.Add("40 2 2 0");
            WillReturn.Add("120 2 3 4");
            WillReturn.Add("30 1 1 0");
            WillReturn.Add("40 2 1 0");
            WillReturn.Add("50 2 2 0");
            WillReturn.Add("60 1 2 0");
            WillReturn.Add("120 3 3 2");
            WillReturn.Add("0 1 1 0");
            WillReturn.Add("1 2 2 0");
            WillReturn.Add("300 5 8 0");
            WillReturn.Add("0 0 0 0");
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static int mT;

    struct SubmitInfoDef
    {
        internal int Team;
        internal int Time;
        internal int Problem;
        internal bool IsAC;
    }
    static List<SubmitInfoDef> mSubmitInfoList = new List<SubmitInfoDef>();

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

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

        int RestSubmitCnt = 0;
        foreach (string EachStr in InputList) {
            SplitAct(EachStr);

            if (RestSubmitCnt == 0) {
                if (wkArr.All(pX => pX == 0)) {
                    break;
                }
                mT = wkArr[1];
                RestSubmitCnt = wkArr[3];
                mSubmitInfoList.Clear();

                if (RestSubmitCnt == 0) {
                    Solve();
                }
                continue;
            }
            SubmitInfoDef WillAdd;
            WillAdd.Time = wkArr[0];
            WillAdd.Team = wkArr[1];
            WillAdd.Problem = wkArr[2];
            WillAdd.IsAC = (wkArr[3] == 0);
            mSubmitInfoList.Add(WillAdd);
            RestSubmitCnt--;

            if (RestSubmitCnt == 0) {
                Solve();
            }
        }
    }

    // チームごとの状況
    class TeamInfoDef
    {
        internal int Team;
        internal int ACCnt;
        internal int WACnt;
        internal int TimeSum;
    }

    static void Solve()
    {
        // 提出時間の昇順(提出時間が同じなら正解が後)
        mSubmitInfoList = mSubmitInfoList.OrderBy(pX => pX.Time).ThenBy(pX => pX.IsAC).ToList();

        // 状況[チーム]
        var TeamInfoDict = new Dictionary<int, TeamInfoDef>();
        for (int I = 1; I <= mT; I++) {
            var WillAdd = new TeamInfoDef();
            WillAdd.Team = I;
            WillAdd.ACCnt = WillAdd.WACnt = WillAdd.TimeSum = 0;
            TeamInfoDict[I] = WillAdd;
        }

        for (int I = 0; I <= mSubmitInfoList.Count - 1; I++) {
            int CurrTeam = mSubmitInfoList[I].Team;
            int CurrProblem = mSubmitInfoList[I].Problem;

            // 不正解はcontinue;
            if (mSubmitInfoList[I].IsAC == false) {
                continue;
            }

            TeamInfoDict[CurrTeam].ACCnt++;
            TeamInfoDict[CurrTeam].TimeSum += mSubmitInfoList[I].Time;

            // WAの分を加算
            for (int J = 0; J <= I - 1; J++) {
                if (mSubmitInfoList[J].Team != CurrTeam) continue;
                if (mSubmitInfoList[J].Problem != CurrProblem) continue;
                TeamInfoDict[CurrTeam].WACnt++;
            }
        }

        // TimeSumにペナルティを加算
        foreach (int EachTeam in TeamInfoDict.Keys.ToArray()) {
            TeamInfoDict[EachTeam].TimeSum += TeamInfoDict[EachTeam].WACnt * 20;
        }

        var ValuesList = TeamInfoDict.Values.ToList();

        // 順位の降順にソート
        ValuesList = ValuesList.OrderByDescending(pX => pX.ACCnt).
            ThenBy(pX => pX.TimeSum).
            ThenByDescending(pX => pX.Team).ToList();

        var WillOutList = new List<string>();
        while (ValuesList.Count > 0) {
            var SameTeamList = new List<int>();
            SameTeamList.Add(ValuesList[0].Team);
            for (int I = 1; I <= ValuesList.Count - 1; I++) {
                if (ValuesList[0].ACCnt != ValuesList[I].ACCnt) break;
                if (ValuesList[0].TimeSum != ValuesList[I].TimeSum) break;
                SameTeamList.Add(ValuesList[I].Team);
            }
            WillOutList.Add(IntEnumJoin("=", SameTeamList));

            ValuesList.RemoveAll(pX => SameTeamList.Contains(pX.Team));
        }

        Console.WriteLine(string.Join(",", WillOutList.ToArray()));
    }

    // セパレータとInt型の列挙を引数として、結合したstringを返す
    static string IntEnumJoin(string pSeparater, IEnumerable<int> pEnum)
    {
        string[] StrArr = Array.ConvertAll(pEnum.ToArray(), pX => pX.ToString());
        return string.Join(pSeparater, StrArr);
    }
}


解説

ナイーブに集計してます。