AtCoderの企業コンテスト
前の企業コンテストの問題へ
CodeQUEEN 2024 決勝 E AtCoder Hotel
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("4 3");
WillReturn.Add("3 5 1 4");
WillReturn.Add("5 3 3");
WillReturn.Add("3 1 1");
WillReturn.Add("2 3 2");
//4
}
else if (InputPattern == "Input2") {
WillReturn.Add("8 5");
WillReturn.Add("2 5 1 5 2 1 2 4");
WillReturn.Add("4 2 5");
WillReturn.Add("7 2 4");
WillReturn.Add("7 4 2");
WillReturn.Add("1 4 7");
WillReturn.Add("3 3 8");
//11
}
else if (InputPattern == "Input3") {
WillReturn.Add("10 1");
WillReturn.Add("1 1 1 1 1 1 1 1 1 1");
WillReturn.Add("10 4 1");
//-1
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
struct RoomInfoDef
{
internal int Rank;
internal int Capacity;
internal int Cost;
}
static List<RoomInfoDef> mRoomInfoList = new List<RoomInfoDef>();
static int[] mAArr;
static int UB;
static void Main()
{
List<string> InputList = GetInputList();
mAArr = InputList[1].Split(' ').Select(pX => int.Parse(pX)).ToArray();
Array.Sort(mAArr);
UB = mAArr.GetUpperBound(0);
int[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();
foreach (string EachStr in InputList.Skip(2)) {
SplitAct(EachStr);
RoomInfoDef WillAdd;
WillAdd.Rank = wkArr[0];
WillAdd.Capacity = wkArr[1];
WillAdd.Cost = wkArr[2];
mRoomInfoList.Add(WillAdd);
}
mRoomInfoList = mRoomInfoList.OrderBy(pX => pX.Rank).ToList();
// 最小コスト[人の割り当て開始添字]
int?[] DPArr = new int?[UB + 1];
DPArr[0] = 0;
bool HasAnswer = false;
int Answer = int.MaxValue; ;
foreach (RoomInfoDef EachRoomInfo in mRoomInfoList) {
for (int I = UB; 0 <= I; I--) {
if (DPArr[I].HasValue == false) continue;
if (EachRoomInfo.Rank >= mAArr[I]) {
int NewVal = DPArr[I].Value + EachRoomInfo.Cost;
int RangeMax = GetRangeMax(EachRoomInfo.Rank, EachRoomInfo.Capacity, I);
int NewI = RangeMax + 1;
if (NewI > UB) {
HasAnswer = true;
Answer = Math.Min(Answer, NewVal);
continue;
}
if (DPArr[NewI].HasValue) {
if (DPArr[NewI].Value <= NewVal) {
continue;
}
}
DPArr[NewI] = NewVal;
}
}
}
if (HasAnswer) {
Console.WriteLine(Answer);
}
else {
Console.WriteLine(-1);
}
}
// 部屋の{ランク,定員}、現在の添字を引数とし、どこまで割り当て可能かを返す
static int GetRangeMax(int pRank, int pCapacity, int pInd)
{
int L = pInd;
int R = pInd + pCapacity - 1;
R = Math.Min(UB, R);
if (mAArr[R] <= pRank) {
return R;
}
while (L + 1 < R) {
int Mid = (L + R) / 2;
if (pRank >= mAArr[Mid]) {
L = Mid;
}
else {
R = Mid;
}
}
return L;
}
}
解説
人は宿泊したい部屋のランクの昇順にソートしておいてから、
ホテルの部屋をランクの昇順に見て、
最小コスト[人の割り当て開始添字]を更新するDPで解いてます。
確保した部屋に、どこまで人を割り当てできるかは、二分法で高速に求めてます。