トップページに戻る
次の競技プログラミングの問題へ
前の競技プログラミングの問題へ
No.78 クジ付きアイスバー
■■■問題■■■
A君は当たりクジ付きのアイスバーが大好きである。
アイスバーには「ハズレ」と「1本当たり」と「2本当たり」がある。
ハズレは何ももらえないが、当たりだとその本数をタダでもらえる。
お店ではアイスバーが箱詰めされて売られている。
1つの箱にはN本のアイスバーが入っている。
A君は箱の先頭から順にしかアイスバーを取り出すことはできない。
買う場合も当たりと引き換えの場合もこの箱からアイスバーを取り出す。
1つの箱の中のハズレと当たりクジの配置はどの箱も同じである。
お店には1つのアイスバーの箱があり、売り切れると1つの新しい箱を補充する。
いまお店には新しい手つかずのアイスバーの箱がある。
A君は最初は「当たり」クジを持っておらず予算は無限にある。
K本のアイスバーを食べるためにはA君は最低何本のアイスを買う必要があるか?
■■■入力■■■
N K
S
Nは1箱に入っているアイスバーの数。1 <= N <= 50。Nは正の整数。
KはA君が食べる予定のアイスバーの数。1 <= K <= 20億。Kは正の整数。
Sの長さはNの値と等しい。
文字列Sは'0'と'1'と'2'の3種類の文字で構成される。
'0'は「ハズレ」、'1'は「1本当たり」、'2'は「2本当たり」をあらわす。
文字列の文字の順番に箱の先頭からアイスバーが入っていると考える。
■■■出力■■■
A君が買うアイスバーの本数を答えよ。
最後に改行を忘れずに。
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("5 4");
WillReturn.Add("01200");
//2
//1つの箱の中には5個のアイスバーが入っている。
//先頭から順に「ハズレ」、「1本当たり」、「2本当たり」、「ハズレ」、「ハズレ」である。
//最初の2本のアイスバーは購入しなければならない。
//2本目のアイスバーは「1本当たり」であるので3本目のアイスバーはタダでもらえる。
//3本目のアイスバーは「2本当たり」であるので4,5本目のアイスバーもタダでもらえる。
//A君が食べたいアイスバーの数は4本なのでこの時点で目的は達成した。
//A君が購入したアイスバーは2本である。
}
else if (InputPattern == "Input2") {
WillReturn.Add("2 8");
WillReturn.Add("10");
//4
//1つのアイスバーの箱に2本のアイスバーが入っている。
//箱には「1本当たり」、「ハズレ」の順番でアイスバーが入っている。
//1本買うたびに1本もらえるので1本買うと2本食べれると考える。
//よって、8本食べるには4本の購入が必要となる。
}
else if (InputPattern == "Input3") {
WillReturn.Add("10 100");
WillReturn.Add("2222222222");
//1
//1つの箱に「2本当たり」のアイスバーが10本入っている。
//当たりを使ってアイスバーをもらい放題だが最初の1本はどうしても買う必要がある。
}
else if (InputPattern == "Input4") {
WillReturn.Add("2 5");
WillReturn.Add("01");
//3
//1つのアイスバーの箱に2本のアイスバーが入っている。
//箱には「ハズレ」、「1本当たり」の順番でアイスバーが入っている。
//5本のアイスバーを食べるには3本のアイスバーの購入が必要である。
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static int K;
static char[] SArr;
static void Main()
{
List<string> InputList = GetInputList();
K = int.Parse(InputList[0].Split(' ').Last());
SArr = InputList[1].ToCharArray();
Console.WriteLine(Solve());
}
static int Solve()
{
int HonsuuSum = 0;
int KounyuuCnt = 0;
int AtariHonsuu = 0;
//1箱分の処理を行う
Action HitohakoSyori = () =>
{
foreach (char EachChar in SArr) {
if (AtariHonsuu == 0) KounyuuCnt++;
else AtariHonsuu--;
if (EachChar == '1') AtariHonsuu++;
if (EachChar == '2') AtariHonsuu += 2;
if (++HonsuuSum == K) {
return;
}
}
};
//1箱目の処理を行う
HitohakoSyori();
//1箱目で指定本数に達した場合
if (HonsuuSum == K) {
return KounyuuCnt;
}
//持ち越した当たり本数を使っての
//次の箱での購入数
int SecondBoxKounyuuCnt = KounyuuCnt - AtariHonsuu;
if (SecondBoxKounyuuCnt <= 0) return KounyuuCnt;
//指定本数までの全箱数
int TotalBoxCnt = K / SArr.Length;
if (K % SArr.Length > 0) TotalBoxCnt++;
//1箱目と最終箱以外の箱数
int RestBoxCnt = TotalBoxCnt - 2;
//1箱目と最終箱以外の箱を一気に処理
if (RestBoxCnt > 0) {
HonsuuSum += RestBoxCnt * SArr.Length;
KounyuuCnt += RestBoxCnt * SecondBoxKounyuuCnt;
}
//最終箱の処理を行う
HitohakoSyori();
return KounyuuCnt;
}
}
解説
TLE対策で、1箱目と最終箱と、これら以外の箱で
進めていく実装としてます。