トップページに戻る
次の競技プログラミングの問題へ
前の競技プログラミングの問題へ
ABC-011-C 123引き算
■■■問題■■■
あなたは、友人から、一人用のゲームを紹介されました。
最初に、数字Nが与えられます。
1,2,3の中から好きな数字を選び、与えられた数字に対し、引き算を行う、
という処理を行うことできます。
この処理は100回まで行うことが可能であり、
最終的に数字を0にすることが目標のゲームです。
しかし、計算途中でなってはいけないNG数字が3つ与えられており、
この数字に一時的にでもなってしまった瞬間、このゲームは失敗となります。
NG数字がNと同じ場合も失敗となります。
あなたは、このゲームが、目標達成可能なゲームとなっているか調べたいです。
目標達成可能な場合は'YES'、そうでない場合は'NO'と出力してください。
■■■入力■■■
N
NG1
NG2
NG3
●1行目には、最初に与えられる数字 N(1 <= N <= 300) が与えられる。
●2行目には、1番目のNG数字 NG1(1 <= NG1 <= 300) が与えられる。
●3行目には、2番目のNG数字 NG2(1 <= NG2 <= 300) が与えられる。
●4行目には、3番目のNG数字 NG3(1 <= NG3 <= 300) が与えられる。
■■■出力■■■
目標達成可能な場合は'YES'、そうでない場合は'NO'を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("2");
WillReturn.Add("1");
WillReturn.Add("7");
WillReturn.Add("15");
//YES
//2を1回引くことにより、0を作ることが出来ます
}
else if (InputPattern == "Input2") {
WillReturn.Add("5");
WillReturn.Add("1");
WillReturn.Add("4");
WillReturn.Add("2");
//YES
//最初に2を引き、次に3を引くことで、5 → 3 → 0 と変化し、
//目標を達成することが出来ます。
}
else if (InputPattern == "Input3") {
WillReturn.Add("300");
WillReturn.Add("57");
WillReturn.Add("121");
WillReturn.Add("244");
//NO
//100回連続で3を引かなければ、目標を達成することはできません。
//しかし、3だけを引き続けていると、
//途中でNG数字である57になってしまいます。
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
int N = int.Parse(InputList[0]);
int[] NGArr = new int[3];
NGArr[0] = int.Parse(InputList[1]);
NGArr[1] = int.Parse(InputList[2]);
NGArr[2] = int.Parse(InputList[3]);
if (NGArr.Contains(N)) {
Console.WriteLine("NO");
return;
}
//到達可能な数値
var PrevDP = new HashSet<int>();
PrevDP.Add(N);
for (int I = 1; I <= 100; I++) {
var CurrDP = new HashSet<int>();
foreach (int EachInt in PrevDP) {
Action<int> AddAct = pNewVal =>
{
if (NGArr.Contains(pNewVal))
return;
if (pNewVal < 0) return;
CurrDP.Add(pNewVal);
};
AddAct(EachInt - 1);
AddAct(EachInt - 2);
AddAct(EachInt - 3);
}
if (CurrDP.Contains(0)) {
Console.WriteLine("YES");
return;
}
PrevDP = CurrDP;
}
Console.WriteLine("NO");
}
}
解説
動的計画法で解いてます。