Created
January 6, 2017 10:39
-
-
Save taross-f/eb61c74b844fedbbe2330bef69a8c678 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Query Kind="Program"> | |
<Reference><RuntimeDirectory>\System.dll</Reference> | |
<Reference><RuntimeDirectory>\System.Net.dll</Reference> | |
<Reference><RuntimeDirectory>\System.Net.Http.dll</Reference> | |
<Reference><RuntimeDirectory>\System.Web.dll</Reference> | |
<NuGetReference>Microsoft.Net.Http</NuGetReference> | |
<NuGetReference>Newtonsoft.Json</NuGetReference> | |
<NuGetReference>Sendgrid</NuGetReference> | |
<Namespace>Newtonsoft.Json</Namespace> | |
<Namespace>Newtonsoft.Json.Bson</Namespace> | |
<Namespace>Newtonsoft.Json.Converters</Namespace> | |
<Namespace>Newtonsoft.Json.Linq</Namespace> | |
<Namespace>Newtonsoft.Json.Schema</Namespace> | |
<Namespace>Newtonsoft.Json.Serialization</Namespace> | |
<Namespace>SendGrid.SmtpApi</Namespace> | |
<Namespace>System.IO</Namespace> | |
<Namespace>System.Net</Namespace> | |
<Namespace>System.Web.Mail</Namespace> | |
</Query> | |
//using System; | |
//using System.Linq; | |
//using System.Collections.Generic; | |
class EightQueen | |
{ | |
static void Main() | |
{ | |
var n = int.Parse(Console.ReadLine()); | |
var rc = Enumerable.Range(0, n) | |
.Select(_ => Console.ReadLine()); | |
var board = new Board(rc); | |
board.InitAttackedArea(); | |
var resultBoard = board.Explore(); | |
resultBoard.Nodes.ForEach(row => | |
Console.WriteLine(string.Join("", row.Select(x => x.QueenExists ? "Q" : ".").ToArray()))); | |
} | |
} | |
public class Board | |
{ | |
public Node[][] Nodes{ get; set; } | |
const int Size = 8; | |
public Board() {} | |
public Board(IEnumerable<string> rc) | |
{ | |
var queens = rc.Select(x => x.Split()) | |
.Select(x => new | |
{ | |
Row = int.Parse(x[0]), | |
Column = int.Parse(x[1]) | |
}) | |
.ToArray(); | |
Nodes = Enumerable.Range(0, Size) | |
.Select(row => Enumerable | |
.Range(0, Size) | |
.Select(column => new Node | |
{ | |
QueenExists = queens.Any(x => x.Row == row && x.Column == column) | |
}) | |
.ToArray()) | |
.ToArray(); | |
} | |
// 初期配置のアタックエリア設定 | |
public void InitAttackedArea() | |
{ | |
Nodes.ForEach((x, row) => x.ForEach((node, column) => | |
{ | |
ApplyAttackedArea(row, column); | |
})); | |
} | |
public void ApplyAttackedArea(int row, int column) | |
{ | |
var node = Nodes[row][column]; | |
if (!node.QueenExists) | |
return; | |
// row | |
Nodes[row].ForEach(x => | |
{ | |
x.IsAttackedArea = true; | |
}); | |
// column | |
Nodes.ForEach(rows => | |
{ | |
rows[column].IsAttackedArea = true; | |
}); | |
// from left top to right bottom | |
for (int r = row - Size, c = column - Size; r < Size && c < Size; r++, c++) | |
{ | |
// 一旦はみ出させてループを開始しているので、はみ出している場合はチェックしない | |
if (r >= Size || c >= Size || r < 0 || c < 0) | |
continue; | |
Nodes[r][c].IsAttackedArea = true; | |
} | |
// from right top to left bottom | |
for (int r = row - Size, c = column + Size; r < Size && c >= 0; r++, c--) | |
{ | |
// 一旦はみ出させてループを開始しているので、はみ出している場合はチェックしない | |
if (r >= Size || c >= Size || r < 0 || c < 0) | |
continue; | |
Nodes[r][c].IsAttackedArea = true; | |
} | |
} | |
public Board Clone() | |
{ | |
return new Board | |
{ | |
Nodes = Nodes.Select(x => | |
x.Select(y => new Node | |
{ | |
IsAttackedArea = y.IsAttackedArea, | |
QueenExists = y.QueenExists | |
}) | |
.ToArray()) | |
.ToArray() | |
}; | |
} | |
public Board Explore() | |
{ | |
return Enumerable.Range(0, Size) | |
.Where(row => Nodes[row].All(x => !x.QueenExists)) | |
.Select(row => Enumerable.Range(0, Size) | |
.Select(column => Explore(this, row, column)) | |
.FirstOrDefault(x => x != null)) | |
.DefaultIfEmpty(this) | |
.FirstOrDefault(); | |
} | |
private static Board Explore(Board board, int r, int c) | |
{ | |
if (board.Nodes[r][c].IsAttackedArea) | |
return null; | |
// checkしたよ判定 | |
board.Nodes[r][c].IsAttackedArea = true; | |
// 先がダメだったとき用に先にはクローンしたものを渡す | |
var b = board.Clone(); | |
b.Nodes[r][c].QueenExists = true; | |
// 今回設定したqueenのアタックエリア設定 | |
b.ApplyAttackedArea(r, c); | |
var nextRow = Enumerable.Range(r + 1, Size - (r + 1)) | |
.Where(x => b.Nodes[x].All(node => !node.QueenExists)) | |
.DefaultIfEmpty(Size) | |
.Min(); | |
// 次がなかったら探索終了。ここのboardが上まで帰ってく | |
if (nextRow >= Size) | |
return b; | |
return Enumerable.Range(0, Size) | |
.Where(x => !b.Nodes[nextRow][x].IsAttackedArea) | |
.Select(x => Explore(b, nextRow, x)) | |
.FirstOrDefault(x => x != null); | |
} | |
} | |
public class Node | |
{ | |
public bool QueenExists { get; set; } | |
public bool IsAttackedArea { get; set; } | |
} | |
// これないとめんどくさすぎるので。 | |
public static class MyExtensions | |
{ | |
public static void ForEach<T>(this IEnumerable<T> e, Action<T> action) | |
{ | |
foreach (var element in e) action(element); | |
} | |
public static void ForEach<T>(this IEnumerable<T> e, Action<T, int> action) | |
{ | |
var i = 0; | |
foreach (var element in e) action(element, i++); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment