AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC466-D Placing Rooks
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("3 6");
WillReturn.Add("1 1");
WillReturn.Add("1 2");
WillReturn.Add("3 3");
WillReturn.Add("3 2");
WillReturn.Add("1 3");
WillReturn.Add("1 3");
//2
}
else if (InputPattern == "Input2") {
WillReturn.Add("2 3");
WillReturn.Add("1 2");
WillReturn.Add("2 1");
WillReturn.Add("1 1");
//1
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long[] GetSplitArr(string pStr)
{
return (pStr == "" ? new string[0] : pStr.Split(' ')).Select(pX => long.Parse(pX)).ToArray();
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = GetSplitArr(InputList[0]);
long N = wkArr[0];
// RookのY座標のSet[X座標]
var XSetDict = new Dictionary<long, HashSet<long>>();
// RookのX座標のSet[Y座標]
var YSetDict = new Dictionary<long, HashSet<long>>();
for (long I = 1; I <= N; I++) {
XSetDict[I] = new HashSet<long>();
YSetDict[I] = new HashSet<long>();
}
// (X,Y)のRookを消す
Action<long, long> RemoveRook = (pX, pY) =>
{
XSetDict[pY].Clear();
YSetDict[pX].Clear();
};
Action<string> SplitAct = (pStr) => wkArr = GetSplitArr(pStr);
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
long TargetY = wkArr[0];
long TargetX = wkArr[1];
foreach (long EachX in XSetDict[TargetY].ToArray()) {
RemoveRook(EachX, TargetY);
}
foreach (long EachY in YSetDict[TargetX].ToArray()) {
RemoveRook(TargetX, EachY);
}
XSetDict[TargetY].Add(TargetX);
YSetDict[TargetX].Add(TargetY);
}
long Answer = 0;
for (long I = 1; I <= N; I++) {
Answer += XSetDict[I].Count;
Answer += YSetDict[I].Count;
}
Console.WriteLine(Answer / 2);
}
}
解説
8王妃問題のルークで行うと考えることができます。
ダイソーのオセロセットで考察すると、
□□□□□□R□
□□□R□□□□
□□R□□□□□
□R□□□□□□
□□□□R□□□
□□□□□□□R
□□□□□R□□
R□□□□□□□
新たにルークを置く際に
同じY座標のルークと、同じX座標のルークの位置を高速に取得でき、
削除も高速にできれば良いと分かります。
これには、
ルークのX座標のSet[Y座標]と
ルークのY座標のSet[X座標]を持ち、
ルークを削除する際は、
ルークの座標を引数としたラムダ式を用意しておいて、
呼べば良いと分かります。
最後には、
ルークのX座標のSet[Y座標]と
ルークのY座標のSet[X座標]を集計し、
2で割れば解が分かります。